From 5e85ad19e15c41659430760f971418a6dbef2192 Mon Sep 17 00:00:00 2001 From: Luis Majano Date: Thu, 5 Sep 2024 00:12:44 +0200 Subject: [PATCH] wip on getting BoxLang certified and running with BX classes --- .gitignore | 1 + server-boxlang@1.json | 13 +- system/Assertion.cfc | 2 +- system/TestBox.cfc | 27 +- system/TestResult.cfc | 4 +- system/mockutils/MockGenerator.cfc | 5 + system/runners/HTMLRunner.cfm | 2 +- test-browser/index.cfm | 2 +- test-harness/runner.cfm | 4 +- test-runner/index.cfm | 2 +- tests/coverageReport.json | 1 - tests/runner.cfm | 2 +- tests/runners/cf9runner.cfm | 4 - tests/specs/AssertionsTest.cfc | 2 +- tests/specs/BDDTest.cfc | 4 +- ...ionscf9Test.cfc => BaseAssertionsTest.cfc} | 9 +- tests/specs/BoxLangTest.bx | 426 ++++++++++++++++++ 17 files changed, 472 insertions(+), 38 deletions(-) delete mode 100644 tests/coverageReport.json delete mode 100644 tests/runners/cf9runner.cfm rename tests/specs/{Assertionscf9Test.cfc => BaseAssertionsTest.cfc} (97%) create mode 100644 tests/specs/BoxLangTest.bx diff --git a/.gitignore b/.gitignore index 6b525673..a02e64dc 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ /settings.xml .settings/ .engine/ +grapher/** # Test Results tests/results/** diff --git a/server-boxlang@1.json b/server-boxlang@1.json index 31111aa2..ae074bd7 100644 --- a/server-boxlang@1.json +++ b/server-boxlang@1.json @@ -3,7 +3,7 @@ "cfengine":"boxlang@be", "serverHomeDirectory":".engine/boxlang" }, - "name":"coldbox-boxlang", + "name":"testbox-boxlang", "force":true, "openBrowser":false, "web":{ @@ -19,15 +19,16 @@ } }, "JVM":{ - "heapSize":"1024" + "heapSize":"1024", + "javaVersion":"openjdk21_jdk" }, "cfconfig":{ "file":".cfconfig.json" }, "env":{ - "BOXLANG_DEBUG": true + "BOXLANG_DEBUG":true }, - "scripts" : { - "onServerInitialInstall":"install bx-compat" - } + "scripts":{ + "onServerInitialInstall":"install bx-compat,bx-unsafe-evaluate" + } } diff --git a/system/Assertion.cfc b/system/Assertion.cfc index 0eb6316f..fcc646a2 100644 --- a/system/Assertion.cfc +++ b/system/Assertion.cfc @@ -649,7 +649,7 @@ component { } // diff message types arguments.message = ( - len( arguments.message ) ? arguments.message : "The incoming function threw exception [#e.type#] [#e.message#] [#e.detail#] different than expected params type=[#arguments.type#], regex=[#arguments.regex#]" + len( arguments.message ) ? arguments.message : "The incoming function threw exception [type: #e.type#] [message: #e.message#] [#e.detail#] different than expected params type=[#arguments.type#], regex=[#arguments.regex#]" ); detail = e.stackTrace; } diff --git a/system/TestBox.cfc b/system/TestBox.cfc index 2ad760d9..2ad078bc 100644 --- a/system/TestBox.cfc +++ b/system/TestBox.cfc @@ -29,11 +29,12 @@ component accessors="true" { property name="coverageService"; // TestBox Modules Registry property name="modules"; - // A list of globbing patterns to match bundles to test ONLY! Ex: *Spec,*Test + // A list of globbing patterns to match bundles to test ONLY! Ex: *Spec|*Test property name="bundlesPattern"; // Constants variables.TESTBOX_PATH = expandPath( "/testbox" ); + variables.IS_BOXLANG = server.keyExists( "boxlang" ); /** * Constructor @@ -54,14 +55,14 @@ component accessors="true" { any labels = [], any excludes = [], struct options = {}, - string bundlesPattern = "*.cfc" + string bundlesPattern = "*.bx|*.cfc" ){ // TestBox version variables.version = "@build.version@+@build.number@"; variables.codename = ""; // Bundles pattern if ( !len( arguments.bundlesPattern ) ) { - arguments.bundlesPattern = "*.cfc"; + arguments.bundlesPattern = "*.bx|*.cfc"; } variables.bundlesPattern = arguments.bundlesPattern; // Utility and mappings @@ -820,7 +821,8 @@ component accessors="true" { * @directory The directory information struct to test: [ mapping = the path to the directory using dot notation (myapp.testing.specs), recurse = boolean, filter = closure that receives the path of the class found, it must return true to process or false to continue process ] */ private function getSpecPaths( required directory ){ - var results = []; + var results = []; + var pathPatternMatcher = new testbox.system.modules.globber.models.PathPatternMatcher(); // recurse default arguments.directory.recurse = ( @@ -835,9 +837,12 @@ component accessors="true" { bundleExpandedPath, arguments.directory.recurse, "path", - variables.bundlesPattern, - "asc" - ); + "", + "asc", + "file" + ).filter( ( path ) => { + return pathPatternMatcher.matchPatterns( variables.bundlesPattern.listToArray( "|" ), path ); + } ); // cleanup paths and store them for usage for ( var x = 1; x lte arrayLen( bundlesFound ); x++ ) { @@ -850,9 +855,14 @@ component accessors="true" { continue; } + // If not in BoxLang, skip bx bundles + if ( !variables.IS_BOXLANG and bundlesFound[ x ].listLast( "." ) eq "bx" ) { + continue; + } + // standardize paths bundlesFound[ x ] = reReplace( - replaceNoCase( bundlesFound[ x ], ".cfc", "" ), + reReplaceNoCase( bundlesFound[ x ], "\.(bx|cfc)", "" ), "(\\|/)", "/", "all" @@ -861,7 +871,6 @@ component accessors="true" { bundlesFound[ x ] = replace( bundlesFound[ x ], bundleExpandedPath, "" ); // Clean out slashes and append the mapping. bundlesFound[ x ] = arguments.directory.mapping & reReplace( bundlesFound[ x ], "(\\|/)", ".", "all" ); - arrayAppend( results, bundlesFound[ x ] ); } diff --git a/system/TestResult.cfc b/system/TestResult.cfc index e0067798..cd8d942b 100644 --- a/system/TestResult.cfc +++ b/system/TestResult.cfc @@ -93,9 +93,9 @@ component accessors="true" { variables.coverageData = {}; // CFML Engine + Version - variables.CFMLEngine = server.coldfusion.productName; + variables.CFMLEngine = server.keyExists( "boxlang" ) ? "BoxLang" : server.coldfusion.productName; variables.CFMLEngineVersion = ( - structKeyExists( server, "lucee" ) ? server.lucee.version : server.coldfusion.productVersion + server.keyExists( "boxlang" ) ? server.boxlang.version : server.keyExists( "lucee" ) ? server.lucee.version : server.coldfusion.productVersion ); return this; diff --git a/system/mockutils/MockGenerator.cfc b/system/mockutils/MockGenerator.cfc index 3c1a1568..17dd345e 100644 --- a/system/mockutils/MockGenerator.cfc +++ b/system/mockutils/MockGenerator.cfc @@ -480,9 +480,14 @@ A mock generator udfOut.append( "#instance.lb#" ); } + writeDump( var = arguments.md, top = 10 ); + // Check extends and recurse if ( structKeyExists( arguments.md, "extends" ) ) { for ( var thisKey in arguments.md.extends ) { + writeDump( var = thisKey, top = 10 ); + writeDump( var = arguments.md.extends[ thisKey ], top = 10 ); + abort; generateMethodsFromMD( udfOut, arguments.md.extends[ thisKey ] ); } } diff --git a/system/runners/HTMLRunner.cfm b/system/runners/HTMLRunner.cfm index 89de6177..3ae94f92 100644 --- a/system/runners/HTMLRunner.cfm +++ b/system/runners/HTMLRunner.cfm @@ -10,7 +10,7 @@ - + diff --git a/test-browser/index.cfm b/test-browser/index.cfm index 494231b9..24e26e35 100644 --- a/test-browser/index.cfm +++ b/test-browser/index.cfm @@ -91,7 +91,7 @@ - +
diff --git a/test-harness/runner.cfm b/test-harness/runner.cfm index 182a20cb..bcddd28d 100644 --- a/test-harness/runner.cfm +++ b/test-harness/runner.cfm @@ -10,13 +10,13 @@ - + - + diff --git a/test-runner/index.cfm b/test-runner/index.cfm index e006102d..f06be9bc 100644 --- a/test-runner/index.cfm +++ b/test-runner/index.cfm @@ -10,7 +10,7 @@ - + diff --git a/tests/coverageReport.json b/tests/coverageReport.json deleted file mode 100644 index 956b0e98..00000000 --- a/tests/coverageReport.json +++ /dev/null @@ -1 +0,0 @@ -{"COLUMNS":["filePath","relativeFilePath","filePathHash","numLines","numCoveredLines","numExecutableLines","percCoverage","lineData"],"DATA":[["/Users/lmajano/Sites/projects/TestBox/tests/CoverageReporterTest.cfc","CoverageReporterTest.cfc","B506E28C0CC6B7939E1A86ED7ACDA3B2",3,2,0,1,{"2":"1","1":1}],["/Users/lmajano/Sites/projects/TestBox/tests/CoverageServiceTest.cfc","CoverageServiceTest.cfc","7F968BF64B0F50B6BA8988D55B3B17EE",3,0,0,1,{}]]} \ No newline at end of file diff --git a/tests/runner.cfm b/tests/runner.cfm index a2062a73..34765d77 100644 --- a/tests/runner.cfm +++ b/tests/runner.cfm @@ -16,7 +16,7 @@ - + - -#r.run(reporter="simple")# \ No newline at end of file diff --git a/tests/specs/AssertionsTest.cfc b/tests/specs/AssertionsTest.cfc index b92ecfed..bc3adb44 100644 --- a/tests/specs/AssertionsTest.cfc +++ b/tests/specs/AssertionsTest.cfc @@ -1,7 +1,7 @@ component displayName="TestBox xUnit suite for cf10 and above" labels ="lucee,cf" - extends ="Assertionscf9Test" + extends ="BaseAssertionsTest" { function beforeTests(){ diff --git a/tests/specs/BDDTest.cfc b/tests/specs/BDDTest.cfc index 0ce5ba27..a14cfddf 100644 --- a/tests/specs/BDDTest.cfc +++ b/tests/specs/BDDTest.cfc @@ -89,10 +89,10 @@ component extends="testbox.system.BaseSpec" { it( "can validate instance types", function(){ expect( this ).toBeInstanceOf( "testbox.system.BaseSpec" ); - expect( now() ).toBeInstanceOf( "java.util.Date" ); + expect( createObject( "java", "java.util.Date" ).init() ).toBeInstanceOf( "java.util.Date" ); expect( [] ).toBeInstanceOf( "java.util.List" ); expect( {} ).toBeInstanceOf( "java.util.Map" ); - expect( queryNew( "" ) ).notToBeInstanceOf( "Query" ); + expect( [] ).notToBeInstanceOf( "Query" ); } ); it( "can validate json", function(){ diff --git a/tests/specs/Assertionscf9Test.cfc b/tests/specs/BaseAssertionsTest.cfc similarity index 97% rename from tests/specs/Assertionscf9Test.cfc rename to tests/specs/BaseAssertionsTest.cfc index 76099c66..9d2b300b 100644 --- a/tests/specs/Assertionscf9Test.cfc +++ b/tests/specs/BaseAssertionsTest.cfc @@ -1,8 +1,4 @@ -component - displayName="TestBox xUnit suite for CF9" - labels ="lucee,cf" - extends ="testbox.system.BaseSpec" -{ +component labels="lucee,cf" extends="testbox.system.BaseSpec" { /*********************************** LIFE CYCLE Methods ***********************************/ @@ -133,7 +129,8 @@ component $assert.isEqual( f1, f1 ); - $assert.isEqual( new testbox.system.MockBox(), new testbox.system.MockBox() ); + var target = new testbox.system.MockBox(); + $assert.isEqual( target, target ); var xmlString = ""; $assert.isEqual( xmlParse( xmlString ), xmlParse( xmlString ) ); diff --git a/tests/specs/BoxLangTest.bx b/tests/specs/BoxLangTest.bx new file mode 100644 index 00000000..e948f141 --- /dev/null +++ b/tests/specs/BoxLangTest.bx @@ -0,0 +1,426 @@ +/** + * This tests the BDD functionality in TestBox and BoxLang + */ +class extends="testbox.system.BaseSpec" { + + variables.coldbox = 0; + + /*********************************** LIFE CYCLE Methods ***********************************/ + + function beforeAll(){ + // print( "

BDD Testing is Awesome!

" ); + console( "Executed beforeAll() at #now()# " ); + } + + function afterAll(){ + console( "Executed afterAll() at #now()#" ); + } + + /*********************************** BDD SUITES ***********************************/ + + function run(){ + /** + * describe() starts a suite group of spec tests. + * Arguments: + * + * @title The title of the suite, Usually how you want to name the desired behavior + * @body A closure that will resemble the tests to execute. + * @labels The list or array of labels this suite group belongs to + * @asyncAll If you want to parallelize the execution of the defined specs in this suite group. + * @skip A flag that tells TestBox to skip this suite group from testing if true + */ + describe( + title = "A spec", + labels = "luis", + body = function(){ + // before each spec in THIS suite group + beforeEach( function(){ + coldbox = 0; + coldbox++; + debug( "beforeEach suite: coldbox = #coldbox#" ); + } ); + + // after each spec in THIS suite group + afterEach( function(){ + foo = 0; + } ); + + describe( "A nice /suite/with/slashes", function(){ + it( "can have slashes/inthe/it", function(){ + expect( true ).toBeTrue(); + } ); + } ); + + it( "can match strings with no case sensitivity", function(){ + expect( "Luis" ).toMatch( "^luis" ); + } ); + it( "can match strings with case sensitivity", function(){ + expect( "Luis" ).notToMatchWithCase( "^luis" ); + expect( "luis" ).ToMatchWithCase( "^luis" ); + } ); + + /** + * it() describes a spec to test. Usually the title is prefixed with the suite name to create an expression. + * Arguments: + * + * @title The title of the spec + * @spec A closure that represents the test to execute + * @labels The list or array of labels this spec belongs to + * @skip A flag that tells TestBox to skip this spec from testing if true + */ + it( + title = "is just a closure so it can contain code", + body = function(){ + expect( coldbox ).toBe( 1 ); + }, + labels = "luis" + ); + + it( "can satisfy truth tests", function(){ + expect( 1 ).toSatisfy( function( num ){ + return arguments.num > 0; + } ); + expect( 0 ).notToSatisfy( function( num ){ + return arguments.num > 0; + } ); + + expect( this ).toSatisfy( function( target ){ + return isObject( arguments.target ); + } ); + } ); + + it( "can validate instance types", function(){ + expect( this ).toBeInstanceOf( "testbox.system.BaseSpec" ); + expect( now() ).toBeInstanceOf( "java.util.Date" ); + expect( [] ).toBeInstanceOf( "java.util.List" ); + expect( {} ).toBeInstanceOf( "java.util.Map" ); + expect( queryNew( "" ) ).notToBeInstanceOf( "Query" ); + } ); + + it( "can validate json", function(){ + var data = serializeJSON( { name : "luis", when : now() } ); + expect( "luis" ).notToBeJSON(); + expect( data ).toBeJSON(); + } ); + + // more than 1 expectation + it( "can have more than one expectation test", function(){ + coldbox = coldbox * 8; + // type checks + expect( coldbox ).toBeTypeOf( "numeric" ).toBeNumeric(); + // delta ranges + expect( coldbox ).toBeCloseTo( expected = 10, delta = 2 ); + // negations + expect( coldbox ).notToBe( 4 ); + debug( " >1 expectation tests: coldbox = #coldbox#" ); + } ); + + // ToInclude and ToBeIn + it( "can check includes with strings", function(){ + expect( "Hola luis, how are you" ).toInclude( "luis" ); + expect( "Hola luis, how are you" ).notToInclude( "pete" ); + } ); + it( "can check includes with arrays", function(){ + expect( [ "l", "lui", "luis", "joe" ] ).toInclude( "luis" ); + expect( [ "l", "lui", "joe" ] ).notToInclude( "luis" ); + } ); + it( "can check an expected needle to exist in a string", function(){ + expect( "luis" ).toBeIn( "Hola luis, how are you" ); + expect( "joe" ).notToBeIn( "Hola luis, how are you" ); + } ); + it( "can check an expected needle to exist in an array", function(){ + expect( "luis" ).toBeIn( [ "l", "lui", "luis", "joe" ] ); + expect( "luis" ).notToBeIn( [ "l", "lui", "joe" ] ); + } ); + + // toStartWith + it( "can check if a string starts with the actual value", function(){ + expect( "hello world" ).toStartWith( "hello" ); + expect( "world peace" ).notToStartWith( "hello" ); + } ); + it( "can check if a string starts with the actual value with case-sensitivity", function(){ + expect( "Hello world" ).toStartWithCase( "Hello" ); + expect( "Hello peace" ).notToStartWithCase( "hello" ); + } ); + + // toEndWith + it( "can check if a string ends with the actual value", function(){ + expect( "hello world" ).toEndWith( "LD" ); + expect( "world peace" ).notToEndWith( "world" ); + } ); + it( "can check if a string ends with the actual value with case-sensitivity", function(){ + expect( "Hello world" ).toEndWithCase( "ld" ); + expect( "Hello peace" ).notToEndWithCase( "peeee" ); + } ); + + // negations + it( "can have negative expectations", function(){ + coldbox = coldbox * 8; + // type checks + expect( coldbox ).notToBeTypeOf( "usdate" ); + // dynamic type methods + expect( coldbox ).notToBeArray(); + // delta ranges + expect( coldbox ).notToBeCloseTo( expected = 10, delta = 2 ); + } ); + + it( "can get private properties", function(){ + var oTest = new testbox.tests.resources.Test(); + expect( getProperty( oTest, "reload" ) ).toBeFalse(); + } ); + + // xit() skips + xit( "can have tests that can be skipped easily like this one", function(){ + fail( "xit() this should skip" ); + } ); + + // specs with a random skip closure + it( + title = "can have a skip that is executed at runtime", + body = function(){ + fail( "Skipped programmatically, this should fail" ); + }, + skip = function( spec ){ + spec.name &= " - skipping this because I can!!!"; + return true; + } + ); + + // null expectations + it( "can have null expectations", function(){ + expect( javacast( "null", "" ) ).toBeNull(); + expect( 123 ).notToBeNull(); + } ); + + // discrete math + it( "can have discrete math", function(){ + expect( "d" ).toBeGT( "c" ); + expect( 4 ).toBeGT( 1 ); + + expect( 4 ).toBeGTE( 4 ); + expect( 1 ).toBeLT( 10 ); + expect( 10 ).toBeLTE( 10 ); + } ); + + it( "can test a collection", function(){ + expectAll( [ 2, 4, 6, 8 ] ).toSatisfy( function( x ){ + return 0 == x % 2; + } ); + expectAll( { a : 2, b : 4, c : 6 } ).toSatisfy( function( x ){ + return 0 == x % 2; + } ); + // and we can chain matchers + expectAll( [ 2, 4, 6, 8 ] ).toBeGTE( 2 ).toBeLTE( 8 ); + } ); + + it( "can fail any element of a collection", function(){ + try { + // we need to verify the expectation fails + expectAll( [ 2, 4, 10, 8 ] ).toBeLT( 10 ); + fail( "expectAll() failed to detect a bad element" ); + } catch ( any e ) { + expect( e.message ).toBe( "The actual [10] is not less than [10]" ); + } + } ); + + it( "can process structure key expectations", function(){ + var s = { "data" : {}, "error" : {}, "name" : {}, "age" : 0 }; + + expect( s ).toHaveKey( "error" ); + expect( s ).notToHaveKey( "luis" ); + + // Multiple + expect( s ).toHaveKey( "data,error,name,age" ); + expect( function(){ + expect( s ).toHaveKey( "data,error,name,age2" ); + } ).toThrow(); + expect( s ).notToHaveKey( "luis,joe,tom" ); + expect( function(){ + expect( s ).toHaveKey( "luis,joe,data" ); + } ).toThrow(); + } ); + } + ); + + // Custom Matchers + describe( "Custom Matchers", function(){ + beforeEach( function(){ + // add custom matchers + addMatchers( { + toBeReallyFalse : function( expectation, args = {} ){ + expectation.message = ( + structKeyExists( args, "message" ) ? args.message : "[#expectation.actual#] is not really false" + ); + if ( expectation.isNot ) return ( expectation.actual eq true ); + else return ( expectation.actual eq false ); + }, + toBeReallyTrue : function( expectation, args = {} ){ + expectation.message = ( + structKeyExists( args, "message" ) ? args.message : "[#expectation.actual#] is not really true" + ); + if ( expectation.isNot ) return ( expectation.actual eq false ); + else return ( expectation.actual eq true ); + } + } ); + foo = false; + } ); + + it( "are cool and foo should be really false", function(){ + expect( foo ).toBeReallyFalse(); + } ); + + it( "are still cool and the negation of foo should be really true", function(){ + expect( foo ).notToBeReallyTrue(); + } ); + + // Custom Matchers + describe( "Nested suite: Testing loading via a CFC", function(){ + beforeEach( function(){ + // add custom matcher via CFC + addMatchers( new testbox.tests.resources.CustomMatcher() ); + foofoo = false; + } ); + + it( "should be awesome", function(){ + expect( foofoo ).toBeAwesome(); + debug( " foofoo should be awesome #foofoo#" ); + } ); + + it( "should know its maker", function(){ + expect( "Luis Majano" ).toBeLuisMajano(); + } ); + + describe( "Yet another nested suite", function(){ + it( "should have cascaded beforeEach() call from parent", function(){ + expect( foofoo ).toBeAwesome(); + } ); + + it( "should have cascaded beforeEach() call from grandparent", function(){ + expect( foo ).toBeFalse(); + } ); + } ); + } ); + + // Another suite + describe( "Another Nested Suite", function(){ + it( "can also be awesome", function(){ + expect( foo ).toBeFalse(); + } ); + } ); + } ); + + // skip() by inline function call + describe( + title = "A suite that gets skipped inline via skip()", + body = function(){ + it( "should be skipped", function(){ + skip(); + } ); + } + ); + + + // xdescribe() skips the entire suite + xdescribe( "A suite that is skipped via xdescribe()", function(){ + it( "will never execute this", function(){ + fail( "This should not have executed" ); + } ); + } ); + + describe( "A calculator test suite", function(){ + // before each spec in THIS suite group + beforeEach( function(){ + request.calc = calc = new testbox.tests.resources.Calculator(); + } ); + + // after each spec in THIS suite group + afterEach( function(){ + structDelete( variables, "calc" ); + } ); + + it( "Can have a separate beforeEach for this suite", function(){ + expect( request.calc ).toBeComponent(); + } ); + + xit( "can add incorrectly and fail", function(){ + var r = calc.add( 2, 2 ); + expect( r ).toBe( 5 ); + } ); + + it( "cannot divide by zero", function(){ + expect( function(){ + request.calc.divide( 4, 0 ); + } ).toThrow( regex = "zero" ); + } ); + + it( "cannot divide by zero with message regex", function(){ + expect( function(){ + request.calc.divide( 3, 0 ); + } ).toThrow( regex = "zero" ); + } ); + + it( "can do throws with no message", function(){ + expect( function(){ + request.calc.divideNoMessage(); + } ).toThrow( type = "DivideByZero" ); + } ); + + it( "can do throws with message and detail regex", function(){ + expect( function(){ + request.calc.divideWithDetail(); + } ).toThrow( regex = "(zero|impossible)" ); + + expect( function(){ + request.calc.divideWithDetail(); + } ).toThrow( regex = "impossible" ); + } ); + + it( "can use a mocked stub", function(){ + c = createStub().$( "getData", 4 ); + r = calc.add( 4, c.getData() ); + expect( r ).toBe( 8 ); + expect( c.$once( "getData" ) ).toBeTrue(); + } ); + + xit( "can produce errors", function(){ + exxpect(); + } ); + + it( "can mock any type of data", function(){ + var data = mockData( name: "name", age: "age", id: "uuid" ); + debug( data ); + expect( data ).notToBeEmpty(); + } ); + + it( "can load the output utilities into request.testbox", function(){ + expect( request.testbox ).toHaveKey( "clearDebugBuffer,console,debug,print,println" ); + } ); + } ); + + describe( "In depth throwing exceptions", function(){ + it( "throws a FooException", function(){ + expect( function(){ + throw( type = "FooException" ); + } ).toThrow( "FooException" ); + } ); + it( "won't throw a FooException because nothing is thrown", function(){ + expect( function(){ + } ).notToThrow( "FooException" ); + } ); + it( "won't throw a FooException because a different exception is thrown", function(){ + expect( function(){ + throw( type = "DifferentException" ); + } ).notToThrow( "FooException" ); + } ); + it( "will fail when no regex provided if any exception occurs", function(){ + // Exception Inception! + expect( function(){ + expect( function(){ + throw( type = "AnyException" ); + } ).notToThrow(); + } ).toThrow( "TestBox.AssertionFailed" ); + } ); + } ); + } + +}