This commit is contained in:
msyu
2024-10-23 11:17:42 +03:00
commit ab5c944862
380 changed files with 55823 additions and 0 deletions
+29
View File
@@ -0,0 +1,29 @@
<cfcomponent>
<cfset this.name = 'Taffy_testSuite' /> <!---uses the same application name as the api Application.cfc for scope sharing --->
<cfset this.appDirectory = getDirectoryFromPath(getCurrentTemplatePath())>
<cfset this.parentDirectory = reReplace(this.appDirectory, "(.+[/\\])tests[/\\]$", "\1")>
<cfset this.mappings = structNew()>
<cfset this.mappings["/mxunit"] = this.parentDirectory & "testbox/system/compat/">
<cfset this.mappings["/testbox"] = this.parentDirectory & "testbox/">
<cfset this.mappings["/Hoth"] = this.parentDirectory & "Hoth/">
<cfset this.mappings["/di1"] = this.parentDirectory & "di1/">
<cfset this.mappings["/bugLog"] = this.parentDirectory & "BugLogHQ/">
<cfscript>
//remove bugLogHQ Application.cfc so we can override datasource definition
if (fileExists("#this.parentDirectory#/BugLogHQ/Application.cfc")) {
fileDelete("#this.parentDirectory#/BugLogHQ/Application.cfc");
}
</cfscript>
<cffunction name="onRequestStart" returnType="void" access="public" output="false">
<cfif NOT isDefined('application._taffy')>
<cfset local.apiRootURL = getDirectoryFromPath(cgi.script_name) />
<cfset local.apiRootURL = listDeleteAt(local.apiRootURL,listLen(local.apiRootURL,'/'),'/') />
<cfhttp method="GET" url="http://#CGI.SERVER_NAME#:#CGI.SERVER_PORT##local.apiRootURL#/index.cfm" />
</cfif>
</cffunction>
</cfcomponent>
+207
View File
@@ -0,0 +1,207 @@
<cfcomponent hint="automatic test suite runner">
<cfset this.s_results = StructNew()>
<cfset this.s_results.Errors = StructNew()>
<cfset sep = createObject("java","java.lang.System").getProperty("file.separator")>
<cffunction name="run" access="public" hint="runs a directory of tests" returntype="any" output="false">
<cfargument name="directory" required="true" hint="directory of tests to run">
<cfargument name="componentPath" required="false" hint="the component path to put in front of all tests found (i.e. 'com.blah'). If no path is passed, we'll attempt to discover it ourselves" default="">
<cfargument name="recurse" required="false" type="boolean" default="true" hint="whether to recurse down the directory tree">
<cfargument name="excludes" required="false" default="" hint="list of Tests, in cfc notation, to exclude. uses ListContains so it's as greedy as possible. Currently does not support ant-style syntax or whole-directory filtering">
<cfargument name="refreshCache" required="false" default="false" hint="flag to indicate whether or not to refresh the CF cache of CFCs. Maybe needed if any of the tests in the directory have not yet been compiled - to do: prove" />
<cfset var testResult = "">
<cfset var files = "">
<cfset var suite = createObject("component","mxunit.framework.TestSuite")>
<cfset var i = 1>
<cfset arguments.directory = normalizeDirectory(arguments.directory)>
<cfif NOT len(arguments.componentPath)>
<cfset arguments.componentPath = getComponentPath(arguments.directory, arguments.refreshCache)>
</cfif>
<cfset files = getTests(arguments.directory,arguments.componentPath,arguments.recurse,trim(arguments.excludes)) />
<cfloop from="1" to="#ArrayLen(files)#" index="i">
<cftry>
<cfset suite.addAll(files[i])>
<cfcatch>
<cfset this.s_results.Errors[files[i]] = cfcatch>
</cfcatch>
</cftry>
</cfloop>
<cfset testResult = suite.run()>
<cfset testResult.mergeErrorsIntoTestResult(this.s_results.Errors)>
<cfreturn testResult>
</cffunction>
<cffunction name="getTests" access="private" output="false">
<cfargument name="directory" required="true" hint="directory of tests to run">
<cfargument name="componentPath" required="true" hint="the component path to put in front of all tests found (i.e. 'com.blah')">
<cfargument name="recurse" required="false" default="true" type="boolean" hint="whether to recurse down the directory tree">
<cfargument name="excludes" required="false" default="" hint="ant-style syntax for excluding single files or directories">
<cfset var q_tests = getDirectoryQuery(directory,recurse)>
<cfset var a_tests = ArrayNew(1)>
<cfset var testPath = "">
<cfloop query="q_tests">
<cfset testPath = formatTestPath(arguments.directory, q_tests.directory & sep & q_tests.Name,arguments.componentPath)>
<cfif accept(testPath,arguments.excludes)>
<cftry>
<!---
Compile first. This ensures that any new tests NOT found in the server cache get added.
This may actually be quicker than searching the array and then conditionally compiling.
Appears not to have much overhead, but, we should monitor anyway for large test runs.
--->
<cfset createObject("component","#testPath#") />
<cfcatch type="any"><!--- no worries ---></cfcatch>
</cftry>
<cfset ArrayAppend(a_tests,testPath)>
</cfif>
</cfloop>
<cfreturn a_tests>
</cffunction>
<cffunction name="formatTestPath" access="private" output="false">
<cfargument name="directory" required="true" hint="directory of tests to run">
<cfargument name="fullFilePath">
<cfargument name="componentPath" required="true" hint="the component path to put in front of all tests found (i.e. 'com.blah')">
<cfset var formatted = replaceNoCase(fullFilePath,directory,"")>
<cfset formatted = reverse( replace(reverse(formatted),"cfc.","") )>
<cfset formatted = componentPath & "." & formatted>
<cfset formatted = reReplace(formatted, "(\\|/|\.){1,}" ,".","all")>
<cfreturn formatted>
</cffunction>
<cffunction name="getDirectoryQuery" access="private" returntype="query" output="false">
<cfargument name="directory" required="true" hint="directory of tests to run">
<cfargument name="recurse" type="boolean" required="false" default="true" hint="whether to recurse down the directory tree">
<cfset var files = "">
<cfset var runnerUtils = "">
<cfif not DirectoryExists(arguments.directory)>
<cfthrow message="Directory #directory# does not exist">
</cfif>
<cfdirectory action="list" directory="#arguments.directory#" name="files" recurse="#arguments.recurse#" filter="*.cfc">
<cfreturn files>
</cffunction>
<cffunction name="getCatastrophicErrors" output="false">
<cfreturn this.s_results.Errors>
</cffunction>
<cffunction name="accept" hint="rudimentary initial implementation." access="private" output="false">
<cfargument name="test" required="true">
<cfargument name="excludes" required="true">
<cfset var testName = ListLast(arguments.test,".")>
<cfset var thisExclude = "">
<cfif NOT reFindNoCase("^test",testName) AND NOT reFindNoCase("test$",testName)>
<cfreturn false>
</cfif>
<cfif not len(excludes)>
<cfreturn true>
</cfif>
<cfset arguments.test = ListChangeDelims(arguments.test,"/",".")>
<cfloop list="#excludes#" index="thisExclude" delimiters=",">
<cfset thisExclude = replace(thisExclude,"\","/")>
<cfif reFindNoCase("\b#thisExclude#\b",arguments.test)>
<cfreturn false>
</cfif>
</cfloop>
<cfreturn true>
</cffunction>
<cffunction name="normalizeDirectory" hint="makes sure every directory has ending slashes" access="private" output="false">
<cfargument name="Directory" type="string" required="true"/>
<cfset var dir = createObject("java","java.io.File")>
<cfif not DirectoryExists(arguments.directory)>
<cfset arguments.directory = expandPath(arguments.directory) />
<cfif not DirectoryExists(arguments.directory)>
<cfthrow message="Directory #directory# does not exist">
</cfif>
</cfif>
<cfset dir.init(arguments.directory)>
<cfset arguments.directory = dir.getCanonicalPath()>
<cfset arguments.directory = replaceList(arguments.directory,"/,\","#sep#,#sep#")>
<cfset arguments.directory = arguments.directory & sep>
<cfreturn arguments.directory>
</cffunction>
<cffunction name="getComponentPath" access="remote" returntype="string" hint="Given a directory path, returns the corresponding CFC package according to CFMX" output="false">
<cfargument name="path" type="string" required="true" />
<cfargument name="refreshCache" type="boolean" required="false" default="false" />
<cfscript>
var explorer = createObject("component", "CFIDE.componentutils.cfcexplorer");
var target = explorer.normalizePath(arguments.path);
var cfcs = explorer.getcfcs(refreshCache); //true == refresh cache
var cfc = "";
var i = 1 ;
var package = "";
var cfcpath = "";
for(i = 1; i lte arraylen(cfcs); i = i+1){
cfc = cfcs[i];
//Assumes that CF always stores path info with fwd slash
//and strip last element to get path.
cfcpath = ListDeleteAt(cfc.path, listlen(cfc.path,"/"), "/");
//Array of structs. Doesn't seem possible to do binary search
if(cfcpath eq target){
package = cfc.package;
break;
}
}
return package;
</cfscript>
</cffunction>
<cffunction name="getComponentPathx" access="remote" returntype="string" hint="Given a directory path, returns the corresponding CFC package" output="false">
<cfargument name="path" type="string" required="true" />
<cfargument name="refreshCache" type="boolean" required="false" default="false" />
<cfset var files = '' />
<cfset var package = '' />
<cfdirectory action="list" type="file" name="files" directory="#arguments.path#" filter="*.cfc" />
<cfif files.recordCount>
<cfset package = replace(normalizePath(files.directory), '/', '.', 'all') />
</cfif>
<cfreturn package />
</cffunction>
<cffunction name="normalizePath" access="public" returntype="string" output="false">
<cfargument name="path" type="string" required="true" />
<cfif not len(arguments.path)>
<cfreturn arguments.path />
</cfif>
<cfset arguments.path = replace(arguments.path, '\', '/', 'all') />
<cfif right(arguments.path, 1) eq '/'>
<cfset arguments.path = left(arguments.path, len(arguments.path) - 1) />
</cfif>
<cfreturn arguments.path />
</cffunction>
</cfcomponent>
+92
View File
@@ -0,0 +1,92 @@
<cfcomponent output="true">
<cfsetting enablecfoutputonly="true" showdebugoutput="false">
<cffunction name="run" access="remote" output="true" returntype="void" hint="Generates and prints HTML, JUnit style XML, or XML data based on a directory of tests.">
<cfargument name="type" type="string" hint="Specifies the type to run: TestCase(testcase) or Directory Path (dir)" required="true" />
<cfargument name="value" type="string" hint="The value for the type: com.foo.MyTestCase or C:/my/tests/" required="true" />
<cfargument name="packagename" type="string" hint="The package name for JUnitReportTask" required="false" default="mxunit.testresults" />
<cfargument name="outputformat" type="string" hint="Valid Values: HTML,XML, or JUNITXML" required="false" default="junitxml" />
<cfargument name="recurse" required="false" default="true" hint="whether to recurse down the directory tree">
<cfargument name="excludes" required="false" default="" hint="List of files to exclude if type is DIR">
<cfargument name="componentPath" required="false" hint="performance improver: pass the cfc-notation. See DirectoryTestSuite for details." default="">
<cfset var suite = createObject("component","mxunit.framework.TestSuite").TestSuite()/>
<cfset var results = createObject("component","mxunit.framework.TestResult").TestResult()/>
<cfscript>
if(arguments.type is "testcase"){
suite = createObject("component","mxunit.framework.TestSuite").TestSuite();
suite.addAll(arguments.value);
results = suite.run();
}
if(arguments.type is "dir"){
//To Do: add args for recursion, includes, and excludes
if(not isBoolean(arguments.recurse)){
arguments.recurse = false;
}
results = createObject("component","DirectoryTestSuite").run(directory=arguments.value, componentPath=arguments.componentPath, recurse=arguments.recurse, excludes=arguments.excludes);
}
//package name for JUnit reports
results.setPackage(arguments.packagename);
</cfscript>
<!--- Read by Ant client and used to print summary to stdout --->
<cfcookie name="mxunit_summary" value="#results.testRuns#,#results.testErrors#,#results.testFailures#,#results.totalExecutionTime#" />
<!--- write the cookie first --->
<cfset printResults(arguments.outputformat,results) />
<cfreturn />
</cffunction>
<cffunction name="printResults" access="private">
<cfargument name="type">
<cfargument name="results">
<cfoutput>
<cfswitch expression="#type#">
<cfcase value="html">
#trim(arguments.results.getHTMLResults())#
</cfcase>
<cfcase value="xml">
#trim(arguments.results.getXMLResults())#
</cfcase>
<cfcase value="junitxml">
#trim(arguments.results.getJUnitXMLResults())#
</cfcase>
<cfdefaultcase>#trim(arguments.results.getJUnitXMLResults())#</cfdefaultcase>
</cfswitch>
</cfoutput>
</cffunction>
<cffunction name="runFast" access="remote" output="true" returntype="void" hint="Generates and prints HTML, JUnit style XML, or XML data based on a directory of tests.">
<cfargument name="type" type="string" hint="Specifies the type to run: TestCase(testcase) or Directory Path (dir)" required="true" />
<cfargument name="value" type="string" hint="The value for the type: com.foo.MyTestCase or C:/my/tests/" required="true" />
<cfargument name="packagename" type="string" hint="The package name for JUnitReportTask" required="false" default="mxunit.testresults" />
<cfargument name="outputformat" type="string" hint="Valid Values: HTML,XML, or JUNITXML" required="false" default="junitxml" />
<cfargument name="recurse" required="false" default="true" hint="whether to recurse down the directory tree">
<cfargument name="excludes" required="false" default="" hint="List of files to exclude if type is DIR">
<cfargument name="componentPath" required="false" hint="performance improver: pass the cfc-notation. See DirectoryTestSuite for details." default="">
<cfset var suite = createObject("component","mxunit.framework.TestSuite").TestSuite()/>
<cfset var results = createObject("component","mxunit.framework.TestResult").TestResult()/>
<cfscript>
if(arguments.type is "testcase"){
suite = createObject("component","mxunit.framework.TestSuite").TestSuite();
suite.addAll(arguments.value);
results = suite.run();
}
if(arguments.type is "dir"){
//To Do: add args for recursion, includes, and excludes
if(not isBoolean(arguments.recurse)){
arguments.recurse = false;
}
results = createObject("component","DirectoryTestSuite").run(directory=arguments.value, componentPath=arguments.componentPath, recurse=arguments.recurse, excludes=arguments.excludes);
}
//package name for JUnit reports
results.setPackage(arguments.packagename);
</cfscript>
<!--- Read by Ant client and used to print summary to stdout --->
<cfcookie name="mxunit_summary" value="#results.testRuns#,#results.testErrors#,#results.testFailures#,#results.totalExecutionTime#" />
<!--- write the cookie first
<cfset printResults(arguments.outputformat,results) /> --->
<cfreturn />
</cffunction>
</cfcomponent>
+1
View File
@@ -0,0 +1 @@
<cfcomponent extends="mxunit.framework.RemoteFacade"></cfcomponent>
+22
View File
@@ -0,0 +1,22 @@
<cfcomponent extends="base">
<cffunction name="setup">
<cfset reloadFramework()>
</cffunction>
<cfscript>
function beforeTests(){
variables.taffy = createObject("component","taffy.tests.Application");
makePublic(variables.taffy, "getBeanFactory");
variables.factory = variables.taffy.getBeanFactory();
variables.factory.loadBeansFromPath( expandPath('/taffy/tests/resourcesConflict'), 'taffy.tests.resourcesConflict', expandPath('/taffy/tests/resourcesConflict'), true, variables.taffy);
}
function test_conflicting_URIs_get_skipped() {
assertTrue(checkIfOneSkippedRessourceContainsExpectedException("errorCode", "taffy.resources.DuplicateUriPattern"), "Conflicting URIs not showing in errors");
}
</cfscript>
</cfcomponent>
+645
View File
@@ -0,0 +1,645 @@
<cfcomponent extends="base">
<cffunction name="setup">
<cfset reloadFramework()>
</cffunction>
<cfscript>
function beforeTests(){
variables.taffy = createObject("component","taffy.tests.Application");
makePublic(variables.taffy, "getBeanFactory");
variables.factory = variables.taffy.getBeanFactory();
variables.factory.loadBeansFromPath( expandPath('/taffy/tests/resources'), 'taffy.tests.resources', expandPath('/taffy/tests/resources'), true );
}
function test_properly_notifies_unimplemented_mimes(){
makePublic(variables.taffy, "mimeSupported");
// debug(variables.taffy);
// debug(application);
assertFalse(taffy.mimeSupported("DoesNotExist"), "When given a mime type that should not exist, Taffy reported that it did.");
}
function test_properly_notifies_implemented_mimes(){
makePublic(variables.taffy, "mimeSupported");
makePublic(variables.taffy, "inspectMimeTypes");
variables.taffy.inspectMimeTypes('taffy.core.nativeJsonSerializer', variables.taffy.getBeanFactory());
assertTrue(taffy.mimeSupported("json"));
assertTrue(taffy.mimeSupported("text/json"));
assertTrue(taffy.mimeSupported("application/json"));
}
function test_returns_access_control_expose_headers_header(){
local.result = apiCall("get", "/echo/foo.json", "");
assertTrue(structKeyExists(local.result.responseHeader, "Access-Control-Expose-Headers"));
debug(local.result.responseHeader["Access-Control-Expose-Headers"]);
assertTrue(findNoCase("Etag", local.result.responseHeader["Access-Control-Expose-Headers"]));
}
function test_returns_etag_header(){
//both requests should yield the same etag header
local.result = apiCall("get", "/echo/foo.json", "");
local.result2 = apiCall("get", "/echo/foo.json", "");
assertTrue(structKeyExists(local.result.responseHeader, "Etag"));
assertTrue(structKeyExists(local.result2.responseHeader, "Etag"));
assertEquals(local.result2.responseHeader.etag, local.result.responseHeader.etag);
}
function test_returns_304_when_not_modified(){
local.result = apiCall("get", "/echo/foo.json", "");
assertTrue(structKeyExists(local.result.responseHeader, "Etag"));
local.h = {};
local.h['if-none-match'] = local.result.responseHeader.etag;
local.result = apiCall("get", "/echo/foo.json", "", local.h);
debug(local.result);
assertEquals(304, val(local.result.responseHeader.status_code));
}
function test_json_result_is_json(){
local.result = apiCall ("get","/echo/2.json","bar=foo");
// debug(local.result);
assertTrue(isJson(local.result.fileContent), "Expected JSON content back but was not able to identify it as such.");
}
function test_custom_status_is_returned(){
local.result = apiCall("get", "/echo/1.json?foo=bar", "");
// debug(local.result);
// debug(application);
assertEquals(999, local.result.responseHeader.status_code, "Expected status code 999 but got something else.");
}
function test_custom_headers_work(){
local.result = apiCall("get", "/echo/-1.json", "");
// debug(local.result);
assertTrue(structKeyExists(local.result.responseHeader, "x-dude"), "Expected response header `x-dude` but it was not included.");
}
function test_global_headers_work(){
local.result = apiCall("get", "/echo/1.json", "");
// debug(local.result);
assertTrue(structKeyExists(local.result.responseHeader, "x-foo-globalheader"), "Expected response header `x-foo-globalheader` but it was not included.");
}
function test_deserializer_inspection_finds_all_content_types(){
makePublic(variables.taffy, "getSupportedContentTypes");
local.result = variables.taffy.getSupportedContentTypes("taffy.core.baseDeserializer");
// debug(local.result);
assertTrue(structKeyExists(local.result, "application/x-www-form-urlencoded"));
local.result = variables.taffy.getSupportedContentTypes("taffy.core.nativeJsonDeserializer");
// debug(local.result);
assertTrue(structKeyExists(local.result, "application/json"));
assertTrue(structKeyExists(local.result, "text/json"));
assertTrue(structKeyExists(local.result, "application/x-www-form-urlencoded"));
}
function test_deserializer_support_detection_works(){
makePublic(variables.taffy, "contentTypeIsSupported");
// debug(application._taffy.contentTypes);
assertTrue(variables.taffy.contentTypeIsSupported("application/json"));
assertTrue(variables.taffy.contentTypeIsSupported("application/json;v=1"));
assertFalse(variables.taffy.contentTypeIsSupported("application/does-not-exist"));
}
function test_uri_regexes_are_correct(){
makePublic(variables.taffy, "convertURItoRegex");
local.result = taffy.convertURItoRegex("/a/{abc}/b");
// debug(local.result);
assertEquals( "^/a/([^\/]+)/b((?:\.)[^\.\?\/]+)?\/?$", local.result["uriregex"], "Resulted regex did not match expected. (assert 1)");
assertEquals( 1, arrayLen(local.result["tokens"]), "assert 2" );
assertEquals( "abc", local.result["tokens"][1], "assert 3" );
local.result2 = taffy.convertURItoRegex("/a/{abc}");
// debug(local.result2);
assertEquals( "^/a/(?:(?:([^\/\.]+)(?:\.)([a-za-z0-9]+))\/?|([^\/\.]+))((?:\.)[^\.\?\/]+)?\/?$", local.result2["uriregex"], "Resulted regex did not match expected.");
assertEquals( 1, arrayLen(local.result2["tokens"]) );
assertEquals( "abc", local.result2["tokens"][1] );
//custom regexes for tokens
local.result3 = taffy.convertURItoRegex("/a/{b:[a-z]+(?:42){1}}");
// debug(local.result3);
assertEquals( "^/a/([a-z]+(?:42){1})((?:\.)[^\.\?\/]+)?\/?$", local.result3["uriregex"], "Resulted regex did not match expected. (assert 7)");
assertEquals( 1, arrayLen(local.result3["tokens"]), "assert 8" );
assertEquals( "b", local.result3["tokens"][1], "assert 9" );
local.result4 = taffy.convertURItoRegex("/a/{b:[0-4]{1,7}(?:aaa){1}}/c/{d:\d+}");
// debug(local.result4);
assertEquals( "^/a/([0-4]{1,7}(?:aaa){1})/c/(\d+)((?:\.)[^\.\?\/]+)?\/?$", local.result4["uriregex"], "Resulted regex did not match expected. (assert 10)");
assertEquals( 2, arrayLen(local.result4["tokens"]), "assert 11" );
assertEquals( "b", local.result4["tokens"][1], "assert 12" );
assertEquals( "d", local.result4["tokens"][2], "assert 13" );
}
function test_uri_matching_works_with_extension(){
makePublic(variables.taffy, "matchURI");
local.result = variables.taffy.matchURI("/echo/3.json");
// debug(local.result);
assertEquals('^/echo/(?:(?:([^\/\.]+)(?:\.)([a-za-z0-9]+))\/?|([^\/\.]+))((?:\.)[^\.\?\/]+)?\/?$', local.result);
}
function test_uri_matching_works_without_extension(){
makePublic(variables.taffy, "matchURI");
local.result = variables.taffy.matchURI("/echo/3");
// debug(local.result);
assertEquals('^/echo/(?:(?:([^\/\.]+)(?:\.)([a-za-z0-9]+))\/?|([^\/\.]+))((?:\.)[^\.\?\/]+)?\/?$', local.result);
}
function test_uri_matching_works_with_trailing_slash_with_extension(){
makePublic(variables.taffy, "matchURI");
local.result = variables.taffy.matchURI("/echo/3.json/");
// debug(local.result);
assertEquals('^/echo/(?:(?:([^\/\.]+)(?:\.)([a-za-z0-9]+))\/?|([^\/\.]+))((?:\.)[^\.\?\/]+)?\/?$', local.result);
}
function test_uri_matching_works_with_trailing_slash_without_extension(){
makePublic(variables.taffy, "matchURI");
local.result = variables.taffy.matchURI("/echo/3/");
// debug(local.result);
assertEquals('^/echo/(?:(?:([^\/\.]+)(?:\.)([a-za-z0-9]+))\/?|([^\/\.]+))((?:\.)[^\.\?\/]+)?\/?$', local.result);
}
function test_uri_matching_is_sorted_so_static_URIs_take_priority_over_tokens(){
makePublic(variables.taffy, "matchURI");
local.result = variables.taffy.matchURI("/echo/3");
// debug(local.result);
assertEquals('^/echo/(?:(?:([^\/\.]+)(?:\.)([a-za-z0-9]+))\/?|([^\/\.]+))((?:\.)[^\.\?\/]+)?\/?$', local.result);
local.result = variables.taffy.matchURI("/echo/towel");
// debug(local.result);
assertEquals('^/echo/towel((?:\.)[^\.\?\/]+)?\/?$', local.result);
}
function test_request_parsing_works(){
makePublic(variables.taffy,"buildRequestArguments");
local.result = variables.taffy.buildRequestArguments(
regex = '/echo/([^\/\.]+)$',
tokenNamesArray = listToArray("id"),
uri = '/echo/16',
queryString = 'foo=bar&bar=foo',
headers = structNew()
);
// debug(local.result);
assertTrue(structKeyExists(local.result, "foo") && local.result.foo == "bar", "Missing or incorrect value for key `foo`.");
assertTrue(structKeyExists(local.result, "bar") && local.result.bar == "foo", "Missing or incorrect value for key `bar`.");
assertTrue(structKeyExists(local.result, "id") && local.result.id == 16, "Missing or incorrect value for key `id`.");
}
function test_properly_decodes_urlEncoded_put_request_body(){
local.result = apiCall("put", "/echo/99.json", "foo=bar&check=mate");
// debug(local.result);
if (!isJson(local.result.fileContent)){
// debug(local.result.fileContent);
fail("Result was not JSON");
return local.result.fileContent;
}
local.result = deserializeJSON(local.result.fileContent);
assertTrue(structKeyExists(local.result, "foo") && local.result.foo == "bar", "Missing or incorrect value for key `foo`.");
assertTrue(structKeyExists(local.result, "check") && local.result.check == "mate", "Missing or incorrect value for key `check`.");
}
function test_properly_decodes_json_put_request_body(){
local.result = apiCall("put", "/echo/99.json", '{"foo":"bar"}');
// debug(local.result);
if (!isJson(local.result.fileContent)){
fail("Result was not JSON");
return;
}
local.result = deserializeJSON(local.result.fileContent);
// debug(local.result);
assertTrue(structKeyExists(local.result, "foo") && local.result.foo == "bar", "Missing or incorrect value for key `foo`.");
}
function test_properly_decodes_json_post_request_body(){
local.result = apiCall("post", "/echo/99.json", '{"foo":"bar"}');
// debug(local.result);
if (!isJson(local.result.fileContent)){
fail("Result was not JSON");
return;
}
local.result = deserializeJSON(local.result.fileContent);
// debug(local.result);
assertTrue(structKeyExists(local.result, "foo") && local.result.foo == "bar", "Missing or incorrect value for key `foo`.");
}
function test_returns_error_when_requested_mime_not_supported(){
local.h = structNew();
local.h['Accept'] = "application/NOPE";
local.result = apiCall ("get","/echo/2","foo=bar", local.h);
// debug(local.result);
assertEquals(400, local.result.responseHeader.status_code);
assertEquals("Requested mime type is not supported (application/NOPE)", local.result.responseHeader.explanation);
}
function test_extension_takes_precedence_over_accept_header(){
local.headers = structNew();
local.headers["Accept"] = "text/xml";
local.result = apiCall("get","/echo/2.json","foo=bar",local.headers);
// debug(local.result);
assertEquals(999, local.result.responseHeader.status_code);
assertTrue(isJson(local.result.fileContent));
}
function test_allows_regex_as_final_url_value(){
makePublic(variables.taffy, "buildRequestArguments");
local.headers = structNew();
local.headers.Accept = "application/json";
local.tokenArray = arrayNew(1);
arrayAppend(local.tokenArray, "id");
local.result = variables.taffy.buildRequestArguments(
"^/echo/([a-zA-Z0-9_\-\.\+]+@[a-zA-Z0-9_\-\.]+\.?[a-zA-Z]+)((?:\.)[^\.\?]+)?$",
local.tokenArray,
"/echo/foo@bar.com",
"",
local.headers
);
// debug(local.result);
assertTrue(local.result._taffy_mime eq "json", "Did not detect desired return format correctly.");
//full integration test for a@b.c.json
local.result = apiCall("get", "/echo_regex/12345.json", "", {});
// debug(local.result);
assert(isJson(local.result.fileContent), "response was not json");
local.response = deserializeJSON(local.result.fileContent);
assertEquals("12345", local.response.id);
//full integration test for a@b.c (no .json, but with headers)
local.result = apiCall("get", "/echo_regex/12345", "", local.headers);
// debug(local.result);
assert(isJson(local.result.fileContent), "response was not json");
local.response = deserializeJSON(local.result.fileContent);
assertEquals("12345", local.response.id);
}
function test_returns_405_for_unimplemented_verbs(){
local.result = apiCall("delete", "/echo/2.json", "foo=bar");
// debug(local.result);
assertEquals(405, local.result.responseHeader.status_code);
}
function test_test_onTaffyRequest_allow(){
local.result = apiCall("get","/echo/12.json","refuse=false");
// debug(local.result);
assertEquals(999,local.result.responseHeader.status_code);
}
function test_onTaffyRequest_deny(){
local.result = apiCall("get","/echo/12.json","refuse=true");
// debug(local.result);
assertEquals(405,local.result.responseHeader.status_code);
}
function test_getCacheKey_customBehavior() {
local.result = variables.taffy.getCacheKey(
"EchoMember",
{ "foo": "bar" },
"/echo/12.json"
);
assertEquals("echomember_foo", local.result);
}
function test_getCacheKey_defaultBehavior() {
local.args = {
cfc: "EchoMember",
requestArguments: { "default": true },
matchedURI: "/echo/12.json"
};
local.result = variables.taffy.getCacheKey(argumentCollection = local.args);
// ACF and Lucee generate hash code differently
assertEquals("/echo/12.json_#local.args.requestArguments.hashCode()#", local.result);
}
function test_external_file_request_passes_through(){
local.result = getUrl('http://#CGI.SERVER_NAME#:#CGI.SERVER_PORT##replace(cgi.script_name, "/tests/tests/run.cfm", "/tests/someFolder/someOtherFile.cfm")#');
debug(local.result);
assertTrue(findNoCase('woot', local.result.fileContent), "Was not able to get the DMZ file.");
}
function test_tunnel_PUT_through_POST(){
var local = {};
local.headers["X-HTTP-Method-Override"] = "PUT";
local.result = apiCall("post","/echo/tunnel/12.json","", local.headers);
// debug(local.result);
assertEquals(200,local.result.responseHeader.status_code);
local.deserializedContent = deserializeJSON( local.result.fileContent );
// debug( local.deserializedContent );
assertEquals("put", local.deserializedContent.actualMethod);
}
function test_tunnel_DELETE_through_POST(){
var local = {};
local.headers["X-HTTP-Method-Override"] = "DELETE";
local.result = apiCall("post","/echo/tunnel/12.json","", local.headers);
// debug(local.result);
assertEquals(200,local.result.responseHeader.status_code);
local.deserializedContent = deserializeJSON( local.result.fileContent );
// debug( local.deserializedContent );
assertEquals("delete", local.deserializedContent.actualMethod);
}
function test_put_body_is_mime_content(){
var local = {};
local.result = apiCall(
"put",
"/echo/12.json",
'{"foo":"The quick brown fox jumped over the lazy dog."}'
);
// debug(local.result);
assertEquals(200,local.result.responseHeader.status_code);
local.deserializedContent = deserializeJSON( local.result.fileContent );
// debug( local.deserializedContent );
// The service response should contain only the ID parameter, and not anything parsed from the body
assertEquals("foo,id,password,username", listSort(structKeylist(local.deserializedContent), "textnocase"));
assertEquals(12, local.deserializedContent["id"]);
assertEquals("The quick brown fox jumped over the lazy dog.", local.deserializedContent["foo"]);
}
function test_put_body_is_url_encoded_params(){
var local = {};
local.result = apiCall(
"put",
"/echo/12.json",
"foo=yankee&bar=hotel&baz=foxtrot"
);
// debug(local.result);
assertEquals(200,local.result.responseHeader.status_code);
local.deserializedContent = deserializeJSON( local.result.fileContent );
// debug( local.deserializedContent );
// The service response should contain the ID parameter and all parsed form fields from the body
local.sortedKeys = listSort(structKeylist(local.deserializedContent), "textnocase");
//because apparently railo includes fieldnames when ACF doesn't...
assertTrue("bar,baz,foo,id,password,username" eq local.sortedKeys or "bar,baz,fieldnames,foo,id,password,username" eq local.sortedKeys);
assertEquals(12, local.deserializedContent["id"]);
assertEquals("yankee", local.deserializedContent["foo"]);
assertEquals("hotel", local.deserializedContent["bar"]);
assertEquals("foxtrot", local.deserializedContent["baz"]);
}
function test_get_queryString_keys_without_values_returns_empty_string() {
makePublic(variables.taffy, "buildRequestArguments");
var returnedArguments = variables.taffy.buildRequestArguments(
regex = "^/testResource/$",
tokenNamesArray = [],
uri = "/testResource/",
queryString = "keyOne=valueOne&keyTwo=&keyThree=valueThree",
headers = {}
);
assertEquals("", returnedArguments["keyTwo"]);
}
function test_returns_allow_header_for_405(){
local.result = apiCall("delete","/echo/12.json","");
// debug(local.result);
assertEquals(405,local.result.responseHeader.status_code);
assertTrue(structKeyExists(local.result.responseHeader, "allow"),"Expected ALLOW header, but couldn't find it");
}
function test_returns_allow_header_for_get_200(){
local.result = apiCall("get","/echo/tunnel/12.json","");
// debug(local.result);
assertEquals(200,local.result.responseHeader.status_code);
assertTrue(structKeyExists(local.result.responseHeader, "allow"),"Expected ALLOW header, but couldn't find it");
}
function test_returns_allow_header_for_post_201(){
local.result = apiCall("post","/echo/tunnel/12.json","");
// debug(local.result);
assertEquals(201,local.result.responseHeader.status_code);
assertTrue(structKeyExists(local.result.responseHeader, "allow"),"Expected ALLOW header, but couldn't find it");
}
function test_returns_allow_header_for_put_200(){
local.result = apiCall("put","/echo/tunnel/12.json","");
// debug(local.result);
assertEquals(200,local.result.responseHeader.status_code);
assertTrue(structKeyExists(local.result.responseHeader, "allow"),"Expected ALLOW header, but couldn't find it");
}
function test_returns_allow_header_for_delete_200(){
local.result = apiCall("delete","/echo/tunnel/12.json","");
// debug(local.result);
assertEquals(200,local.result.responseHeader.status_code);
assertTrue(structKeyExists(local.result.responseHeader, "allow"),"Expected ALLOW header, but couldn't find it");
}
function test_can_pass_data_from_onTaffyRequest_to_resource(){
local.result = apiCall("get", "/echo/dude.json", "hulk=smash");
// debug(local.result);
local.body = deserializeJSON(local.result.fileContent);
assertTrue(structKeyExists(local.body, "dataFromOTR"));
assertTrue(local.body.dataFromOTR eq "who let the hulk out?!");
}
function test_reload_on_every_request_setting_works(){
application._taffy.settings.reloadOnEveryRequest = false;
local.result = apiCall("get", "/echo/dude.json", "");
// debug(local.result);
assertFalse(structKeyExists(local.result.responseheader, "X-TAFFY-RELOADED"), "Expected reload header to be missing, but it was sent.");
application._taffy.settings.reloadOnEveryRequest = true;
local.result2 = apiCall("get", "/echo/dude.json", "");
// debug(local.result2);
assertTrue(structKeyExists(local.result2.responseheader, "X-TAFFY-RELOADED"), "Expected reload header to be sent, but it was missing.");
}
function test_returns_error_when_resource_throws_exception(){
local.result = apiCall("get", "/throwException.json", "");
// debug(local.result);
assertEquals(500, local.result.responseHeader.status_code);
assertTrue( isJson( local.result.fileContent ), "Response body was not json" );
}
function test_basic_auth_credentials_found(){
local.result = apiCall("get", "/basicauth.json", "", {}, "Towel:42");
// debug(local.result);
assertTrue(isJson(local.result.fileContent));
local.data = deserializeJSON(local.result.fileContent);
assertTrue(structKeyExists(local.data, "username"));
assertEquals("Towel", local.data.username);
assertTrue(structKeyExists(local.data, "password"));
assertEquals("42", local.data.password);
}
function test_getHostname_returns_not_blank(){
local.hostname = variables.taffy.getHostname();
// debug(local.hostname);
assertNotEquals( "", local.hostname );
}
function test_envConfig_is_applied(){
// debug( application._taffy.settings.reloadPassword );
assertEquals( "dontpanic", application._taffy.settings.reloadPassword );
}
function test_use_endpointURLParam_in_GET(){
local.result = apiCall('get','?#application._taffy.settings.endpointURLParam#=/echo/2606.json','');
// debug(local.result);
assertEquals(999,val(local.result.statusCode));
}
function test_use_endpointURLParam_in_POST(){
local.result = apiCall('post','?#application._taffy.settings.endpointURLParam#=/echo/2606.json','bar=foo');
// debug(local.result);
assertEquals(200,val(local.result.statusCode));
}
function test_use_endpointURLParam_in_PUT(){
local.result = apiCall('put','?#application._taffy.settings.endpointURLParam#=/echo/2606.json','bar=foo');
// debug(local.result);
assertEquals(200,val(local.result.statusCode));
}
function test_use_endpointURLParam_in_DELETE(){
local.result = apiCall('delete','?#application._taffy.settings.endpointURLParam#=/echo/tunnel/2606.json','');
// debug(local.result);
assertEquals(200,val(local.result.statusCode));
}
function test_allows_dashboard_when_enabled(){
var restore = application._taffy.settings.disableDashboard;
application._taffy.settings.disableDashboard = false;
local.result = apiCall("get", "/", "");
// debug(local.result);
assertEquals(200, val(local.result.statusCode));
application._taffy.settings.disableDashboard = restore;
}
function test_returns_403_at_root_when_dashboard_disabled_with_no_redirect(){
var restore = application._taffy.settings.disableDashboard;
application._taffy.settings.disableDashboard = true;
local.result = apiCall("get", "/", "");
// debug(local.result);
assertEquals(403, val(local.result.statusCode));
application._taffy.settings.disableDashboard = restore;
}
function test_returns_302_at_root_when_dashboard_disabled_with_redirect(){
var restore1 = application._taffy.settings.disableDashboard;
var restore2 = application._taffy.settings.disabledDashboardRedirect;
application._taffy.settings.disableDashboard = true;
application._taffy.settings.disabledDashboardRedirect = 'https://google.com';
local.result = apiCall("get", "/", "");
// debug(local.result);
assertEquals(302, val(local.result.statusCode));
assertTrue(structKeyExists(local.result.responseHEader, "location"));
assertEquals(application._taffy.settings.disabledDashboardRedirect, local.result.responseHeader.location);
application._taffy.settings.disableDashboard = restore1;
application._taffy.settings.disabledDashboardRedirect = restore2;
}
function test_properly_returns_wrapped_jsonp(){
application._taffy.settings.jsonp = "callback";
local.result = apiCall("get", "/echo/dude.json?callback=zomg", '');
// debug(local.result);
assertEquals('zomg(', left(local.result.fileContent, 5), "Does not begin with call to jsonp callback");
assertEquals(");", right(local.result.fileContent, 2), "Does not end with `);`");
}
function test_properly_handles_arbitrary_cors_headers(){
//see: https://github.com/atuttle/Taffy/issues/144
application._taffy.settings.allowCrossDomain = true;
local.h = { "Access-Control-Request-Headers" = "goat, pigeon, man-bear-pig", "Origin":"http://#cgi.server_name#/"};
local.result = apiCall("get", "/echo/dude.json", "", local.h);
//debug(local.result);
assertTrue(local.result.responseHeader["Access-Control-Allow-Headers"] contains "goat");
assertTrue(local.result.responseHeader["Access-Control-Allow-Headers"] contains "pigeon");
assertTrue(local.result.responseHeader["Access-Control-Allow-Headers"] contains "man-bear-pig");
}
function test_properly_handles_arbitrary_cors_headers_on_error(){
//see: https://github.com/atuttle/Taffy/issues/159
application._taffy.settings.allowCrossDomain = true;
local.h = { "Access-Control-Request-Headers" = "goat, pigeon, man-bear-pig", "Origin":"http://#cgi.server_name#/"};
local.result = apiCall("get", "/throwException.json", "", local.h);
// debug(local.result);
assertTrue(structKeyExists(local.result.responseHeader, "Access-Control-Allow-Origin"));
assertTrue(structKeyExists(local.result.responseHeader, "Access-Control-Allow-Methods"));
assertTrue(structKeyExists(local.result.responseHeader, "Access-Control-Allow-Headers"));
assertTrue(local.result.responseHeader["Access-Control-Allow-Headers"] contains "goat");
assertTrue(local.result.responseHeader["Access-Control-Allow-Headers"] contains "pigeon");
assertTrue(local.result.responseHeader["Access-Control-Allow-Headers"] contains "man-bear-pig");
}
function test_non_struct_json_body_sent_to_resource_as_underscore_body(){
//see: https://github.com/atuttle/Taffy/issues/169
local.result = apiCall("post", "/echo/5", "[1,2,3]");
// debug(local.result);
local.response = deserializeJSON(local.result.fileContent);
assertTrue(structKeyExists(local.response, "_body"));
assertTrue(isArray(local.response._body));
assertTrue(arrayLen(local.response._body) == 3);
}
function test_comma_delim_list_of_uris_for_alias(){
//works with /echo_alias/{ID}
local.result = apiCall("get", "/echo_alias/4", "");
//debug(local.result);
assertEquals(200, val(local.result.statusCode));
assertEquals(serializeJSON({ID="4"}), local.result.fileContent);
//works with /echo_alias
local.result = apiCall("get", "/echo_alias", "");
// debug(local.result);
assertEquals(200, val(local.result.statusCode));
assertEquals(serializeJSON({ID="0"}), local.result.fileContent);
//works with /echo_alias/ (trailing slash)
local.result = apiCall("get", "/echo_alias/", "");
// debug(local.result);
assertEquals(200, val(local.result.statusCode));
assertEquals(serializeJSON({ID="0"}), local.result.fileContent);
//works with /echo_alias?ID=x
local.result = apiCall("get", "/echo_alias", "ID=2");
// debug(local.result);
assertEquals(200, val(local.result.statusCode));
assertEquals(serializeJSON({ID="2"}), local.result.fileContent);
}
</cfscript>
<cffunction name="test_can_upload_a_file">
<cfset var local = structNew() />
<cfset local.apiRootURL = getDirectoryFromPath(cgi.script_name) />
<cfset local.apiRootURL = listDeleteAt(local.apiRootURL,listLen(local.apiRootURL,'/'),'/') />
<cfhttp
url="http://#cgi.server_name#:#cgi.server_port##local.apiRootURL#/index.cfm/upload"
method="post"
result="local.uploadResult">
<cfhttpparam type="file" name="img" file="#expandPath('/taffy/tests/tests/upload.png')#" />
</cfhttp>
<!--- <cfset debug(local.uploadResult) /> --->
<cfset assertTrue(local.uploadResult.statusCode eq "200 OK", "Did not return status 200") />
</cffunction>
<cffunction name="test_throws_exception_when_ressource_uri_doesnt_begin_with_forward_slash">
<cfset assertTrue(checkIfOneSkippedRessourceContainsExpectedException("detail", "The URI (uriWithoutForwardSlash) for `uriDoesntBeginWithForwardSlash` should begin with a forward slash."), "Uri without forward slash not showing in errors")>
</cffunction>
<cffunction name="test_throws_exception_when_alias_ressource_uri_doesnt_begin_with_forward_slash">
<cfset assertTrue(checkIfOneSkippedRessourceContainsExpectedException("detail", "The URI (uriAliasWithoutFowardSlash) for `uriAliasDoesntBeginWithForwardSlash` should begin with a forward slash."), "Uri alias without forward slash not showing in errors")>
</cffunction>
</cfcomponent>
+94
View File
@@ -0,0 +1,94 @@
component extends="base" {
function setup(){
reloadFramework();
}
function teardown() {
reloadFramework();
}
function beforeTests(){
}
function test_loads_directory_named_resources() {
// Setup external factory to read resource directory. Ignore resources that were designed to cause errors.
local.config = {
exclude = ["uriDoesnt","uriAliasDoesnt","conflict"]
};
local.beanFactory = createObject("component", "di1.ioc").init(["/taffy/tests/resources"], local.config);
// Setup Taffy with new bean factory to use and call 'onApplicationStart' to properly initialize.
local.taffy = createObject("component","taffy.tests.Application");
makePublic(local.taffy, "getExternalBeanFactory");
makePublic(local.taffy, "getBeanListFromExternalFactory");
injectMethod(local.taffy, this, "_getVariables", "getVariables");
local.vars = local.taffy.getVariables();
local.vars.framework.beanFactory = local.beanFactory;
local.taffy.onApplicationStart();
// Grab the resource list and compare.
local.resourceList = local.taffy.getBeanListFromExternalFactory(local.taffy.getExternalBeanFactory());
structDelete(local.vars.framework, "beanFactory");
local.taffy.onApplicationStart();
debug("Available resources from external factory: '" & replace(local.resourceList, ",", ", ", "all") & "'");
assert(listLen(local.resourceList) gt 0, "No resources were loaded from the external factory.");
}
function test_loads_explicit_named_resources() {
// Setup external factory to read resource directory. Ignore resources that were designed to cause errors.
local.config = {
exclude = ["uriDoesnt","uriAliasDoesnt","conflict"],
omitDirectoryAliases = true
};
local.beanFactory = createObject("component", "di1.ioc").init(["/taffy/tests/resources"], local.config);
// Setup Taffy with new bean factory to use and call 'onApplicationStart' to properly initialize.
local.taffy = createObject("component","taffy.tests.Application");
makePublic(local.taffy, "getExternalBeanFactory");
makePublic(local.taffy, "getBeanListFromExternalFactory");
injectMethod(local.taffy, this, "_getVariables", "getVariables");
local.vars = local.taffy.getVariables();
local.vars.framework.beanFactory = local.beanFactory;
local.taffy.onApplicationStart();
// Grab the resource list and compare.
debug(local.beanFactory.getBeanInfo());
local.resourceList = local.taffy.getBeanListFromExternalFactory(local.taffy.getExternalBeanFactory());
structDelete(local.vars.framework, "beanFactory");
local.taffy.onApplicationStart();
debug("Available resources from external factory: '" & replace(local.resourceList, ",", ", ", "all") & "'");
//THIS TEST CURRENTLY FAILING DUE TO https://github.com/atuttle/Taffy/issues/276
//assert(listLen(local.resourceList) gt 0, "No resources were loaded from the external factory.");
}
private function _getVariables(){
return variables;
}
}
+101
View File
@@ -0,0 +1,101 @@
<cfcomponent extends="base">
<cfscript>
function setup() {
reloadFramework();
}
function beforeTests(){
request["_testsRunning"] = true;
variables.taffy = createObject("component","taffy.tests.Application");
makePublic(variables.taffy, "getBeanFactory");
variables.factory = variables.taffy.getBeanFactory();
//debug(variables.factory);
variables.factory.loadBeansFromPath( expandPath('/taffy/tests/resources'), 'taffy.tests.resources', expandPath('/taffy/tests/resources'), true, variables.taffy);
}
function test_throws_on_getBean_not_exists(){
var local = {};
local.nonExistentBean = "does_not_exist";
try{
local.result = variables.factory.getBean(local.nonExistentBean);
fail("Expected 'Bean Not Found' exception to be thrown, but none was.");
} catch (Taffy.Factory.BeanNotFound e) {
//debug(e);
assertTrue(findNoCase('not found', e.message) gt 0, "TaffyFactory exception message did not contain the words 'not found'.");
}
}
function test_autowires_properties_in_beans(){
variables.factory.loadBeansFromPath( expandPath('/taffy/tests/resources'), 'taffy.tests.resources', expandPath('/taffy/tests/resources'), true );
local.bean = variables.factory.getBean( 'EchoMember' );
// debug(local.bean);
assertTrue( structKeyExists(local.bean, "dependency1") );
assertFalse( isSimpleValue(local.bean.dependency1) );
}
function test_autowires_setters_in_beans(){
variables.factory.loadBeansFromPath( expandPath('/taffy/tests/resources'), 'taffy.tests.resources', expandPath('/taffy/tests/resources'), true );
local.bean = variables.factory.getBean( 'EchoRegexMember' );
// debug(local.bean);
assertTrue( structKeyExists(local.bean, "dependency2") );
assertFalse( isSimpleValue(local.bean.dependency2) );
}
function test_autowires_properties_in_transients(){
variables.factory.loadBeansFromPath( expandPath('/taffy/tests/resources'), 'taffy.tests.resources', expandPath('/taffy/tests/resources'), true );
local.bean = variables.factory.getBean( 'CustomJsonSerializer' );
// debug(local.bean);
assertTrue( structKeyExists(local.bean, "dependency1") );
assertFalse( isSimpleValue(local.bean.dependency1) );
}
function test_autowires_setters_in_transients(){
variables.factory.loadBeansFromPath( expandPath('/taffy/tests/resources'), 'taffy.tests.resources', expandPath('/taffy/tests/resources'), true );
local.bean = variables.factory.getBean( 'CustomJsonSerializer' );
// debug(local.bean);
assertTrue( structKeyExists(local.bean, "dependency2") );
assertFalse( isSimpleValue(local.bean.dependency2) );
}
function test_skips_resources_with_errors(){
variables.factory.loadBeansFromPath( expandPath('/taffy/tests/resourcesError'), 'taffy.tests.resourcesError', expandPath('/taffy/tests/resourcesError'), true );
// debug(variables.taffy.status);
assertTrue(structKeyExists(variables.taffy.status, "skippedResources"));
}
function test_lists_skipped_resources(){
variables.factory.loadBeansFromPath( expandPath('/taffy/tests/resourcesError'), 'taffy.tests.resourcesError', expandPath('/taffy/tests/resourcesError'), true, variables.taffy);
debug(variables.taffy.status);
assertTrue(structKeyExists(variables.taffy.status, "skippedResources"));
assertTrue( arrayLen(variables.taffy.status.skippedResources) gt 0 );
}
function test_clears_skipped_resources_on_reload(){
variables.factory.loadBeansFromPath( expandPath('/taffy/tests/resourcesError'), 'taffy.tests.resourcesError', expandPath('/taffy/tests/resourcesError'), true, variables.taffy );
// debug(variables.taffy.status);
assertTrue(structKeyExists(variables.taffy.status, "skippedResources"));
assertTrue( arrayLen(variables.taffy.status.skippedResources) gt 0 );
variables.factory.loadBeansFromPath( expandPath('/taffy/tests/resources'), 'taffy.tests.resources', expandPath('/taffy/tests/resources'), true, variables.taffy );
// debug(variables.taffy.status);
assertTrue(structKeyExists(variables.taffy.status, "skippedResources"));
assertTrue( ArrayLen(variables.taffy.status.skippedResources) eq 0, "Expected skipped resources array to be empty but it wasn't" );
}
function test_treats_CRCs_as_transients(){
var local = {};
//this resource+method explicitly sets response status of 999
local.result = apiCall("get", "/echo/2.json", "foo=bar");
// debug(local.result);
assertEquals(999, local.result.responseHeader.status_code);
//this resource+method usees the default response status => 200=passing test, 999=failing test
local.result = apiCall("get", "/echo/tunnel/2.json", "foo=bar");
// debug(local.result);
assertEquals(200, local.result.responseHeader.status_code);
}
</cfscript>
</cfcomponent>
+63
View File
@@ -0,0 +1,63 @@
<cfcomponent extends="base">
<cfscript>
function test_hoth(){
var mockHoth = getMockBox().createMock(className="Hoth.HothTracker", callLogging=true);
var hothAdapter = '';
var fakeError = {};
var callLog = {};
//setup the behaviors we're expecting the adapter to run
//mockHoth.track('{struct}');
mockHoth.$('track', true);
//create hoth adapter to test
hothAdapter = createObject("component", "taffy.bonus.LogToHoth").init(
"Taffy.examples.api_Hoth.resources.HothConfig",
mockHoth
);
//fake error
fakeError.message = "This is a test error";
fakeError.detail = "Rubber Baby Buggy Bumper";
hothAdapter.saveLog(fakeError);
callLog = mockHoth.$callLog();
debug(callLog);
assertTrue(structKeyExists(callLog, "track"), "should call track method");
assertTrue(isStruct(callLog.track[1][1]), "args should be a struct");
assertEquals(callLog.track[1][1].message, fakeError.message);
}
function test_BugLogHQ(){
var blhqSettings = { bugLogListener = "http://#cgi.server_name#:#cgi.server_port#/tests/BugLogHQ/listeners/bugLogListenerREST.cfm" };
var mockBLHQ = new bugLog.client.bugLogService(argumentCollection=blhqSettings);
var blhqAdapter = '';
var fakeError = {};
fakeError.message = "This is a test error";
fakeError.detail = "Rubber Baby Buggy Bumper";
if (structKeyExists(server, "coldfusion") && structKeyExists(server.coldfusion, "productversion")) {
if (val(listFirst(server.coldfusion.productversion)) < 11) {
//datasource definition will only work on CF11+
return;
}
}
mockBLHQ.init(argumentCollection=blhqSettings);
blhqAdapter = createObject("component", "taffy.bonus.LogToBugLogHQ").init(
config=blhqSettings,
tracker=mockBLHQ
);
//fake error
fakeError.message = "This is a test error";
fakeError.detail = "Rubber Baby Buggy Bumper";
blhqAdapter.saveLog(fakeError);
}
</cfscript>
</cfcomponent>
@@ -0,0 +1,40 @@
<cfcomponent extends="base">
<cfscript>
function setup(){
variables.serializer = createObject("component", "taffy.core.baseSerializer");
}
function test_setData_getData(){
variables.serializer.setData(10);
assertEquals(10, variables.serializer.getData());
}
function test_noData_returns_empty_rep_obj(){
local.result = variables.serializer.noData();
local.meta = getMetaData(local.result);
// debug(local.meta);
// debug(local.result.getData());
assertEquals('taffy.core.baseSerializer', local.meta.fullname);
assertEquals("", local.result.getData());
}
function test_withStatus_getStatus(){
variables.serializer.withStatus(42);
assertEquals(42, variables.serializer.getStatus());
}
function test_withStatus_getStatusText(){
variables.serializer.withStatus(404, "Not Found");
assertEquals("Not Found", variables.serializer.getStatusText());
variables.serializer.withStatus(418);
assertEquals("I'm a teapot", variables.serializer.getStatusText());
}
function test_withHeaders_getHeaders(){
local.h = {};
local.h['x-dude'] = 'dude!';
variables.serializer.withHeaders(local.h);
assertEquals(true, structKeyExists(variables.serializer.getHeaders(), "x-dude"));
}
</cfscript>
</cfcomponent>
+50
View File
@@ -0,0 +1,50 @@
component extends="base" {
function beforeTests(){
variables.taffy = createObject("component","taffy.tests.Application");
variables.resource = createObject("component", "taffy.core.resource");
}
function test_representationOf_returns_repClass(){
application._taffy.settings.serializer = "taffy.core.nativeJsonSerializer";
makePublic(variables.resource, "representationOf");
local.result = variables.resource.representationOf(10);
local.meta = getMetadata(local.result);
// debug(local.meta);
assertEquals(true, eventuallyInherits(local.meta, 'taffy.core.baseSerializer'));
}
function test_queryToArray_respects_column_case(){
makePublic(variables.resource, "queryToArray");
local.before = QueryNew("Foo,Bar");
queryAddRow(local.before);
querySetCell(local.before, "Foo", 42, 1);
querySetCell(local.before, "Bar", "fubar", 1);
// debug(local.before);
local.after = variables.resource.queryToArray(local.before);
// debug(local.after);
local.keyList = structKeyList(local.after[1]);
local.serialized = serializeJSON(local.after);
// debug(local.serialized);
assertTrue( (local.keyList eq "Foo,Bar" or local.keyList eq "Bar,Foo"), 'column name case is not as expected');
assertTrue( (local.serialized eq '[{"Foo":42,"Bar":"fubar"}]') or (local.serialized eq '[{"Bar":"fubar","Foo":42}]') );
}
/* recursive method used to check entire inheritance tree to find that a certain parent class exists somewhere within it */
private boolean function eventuallyInherits(required struct md, required string class) {
if (structKeyExists(md, "fullname") && md.fullname eq class) {
return true;
} else {
if (structKeyExists(md, "extends")) {
return eventuallyInherits(md.extends, class);
} else {
return false;
}
}
}
}
+83
View File
@@ -0,0 +1,83 @@
<cfcomponent extends="mxunit.framework.TestCase">
<cffunction name="apiCall" access="private" output="false">
<cfargument name="method" type="string"/>
<cfargument name="uri" type="string"/>
<cfargument name="query" type="string"/>
<cfargument name="headers" type="struct" default="#structNew()#" />
<cfargument name="basicauth" type="string" default="" />
<cfset var local = structNew() />
<cfset local.apiRootURL = getDirectoryFromPath(cgi.script_name) />
<cfset local.apiRootURL = listDeleteAt(local.apiRootURL,listLen(local.apiRootURL,'/'),'/') />
<cfset local.args = {} />
<cfset local.args.method = arguments.method />
<cfset local.args.redirect = false />
<cfset local.args.result = "local.result" />
<cfset local.args.charset = "utf-8" />
<cfif len(arguments.basicauth)>
<cfset local.args.username = listFirst(arguments.basicauth, ":") />
<cfset local.args.password = listRest(arguments.basicAuth, ":") />
</cfif>
<cfset local.args.url = "http://#CGI.SERVER_NAME#:#CGI.SERVER_PORT##local.apiRootURL#/index.cfm#arguments.uri#" />
<cfif lcase(arguments.method) eq "put" or lcase(arguments.method) eq "post">
<cfhttp attributeCollection="#local.args#">
<cfif isJson(query)>
<cfhttpparam type="header" name="Content-Type" value="text/json" />
<cfelse>
<cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded" />
</cfif>
<cfhttpparam type="body" value="#arguments.query#" />
<!--- Add arbitrary headers to request --->
<cfloop item="local.header" collection="#arguments.headers#">
<cfhttpparam type="header" name="#local.header#" value="#arguments.headers[local.header]#" />
</cfloop>
</cfhttp>
<cfelse>
<cfif find('?',local.args.url)>
<cfset local.args.url = '#local.args.url##arguments.query#' />
<cfelse>
<cfset local.args.url = '#local.args.url#?#arguments.query#' />
</cfif>
<cfhttp attributeCollection="#local.args#">
<!--- Add arbitrary headers to request --->
<cfloop item="local.header" collection="#arguments.headers#">
<cfhttpparam type="header" name="#local.header#" value="#arguments.headers[local.header]#" />
</cfloop>
</cfhttp>
</cfif>
<cfreturn local.result />
</cffunction>
<cffunction name="getUrl" access="private" output="false">
<cfargument name="url" type="string" required="true" />
<cfhttp method="get" url="#arguments.url#" result="local.result" />
<cfreturn local.result />
</cffunction>
<cffunction name="checkIfOneSkippedRessourceContainsExpectedException" access="private" output="false" returntype="boolean">
<cfargument name="exceptionAttributeName" type="string" required="true" />
<cfargument name="expectedValue" type="string" required="true" />
<cfset var skippedRessource = "">
<cfset var expectedExceptionAttributeValueFound = 0>
<cfloop array="#application._taffy.status.skippedResources#" index="skippedRessource">
<cfset expectedExceptionAttributeValueFound = structKeyExists(skippedRessource.exception, arguments.exceptionAttributeName) and skippedRessource.exception[arguments.exceptionAttributeName] is arguments.expectedValue>
<cfif expectedExceptionAttributeValueFound>
<cfbreak>
</cfif>
</cfloop>
<cfreturn expectedExceptionAttributeValueFound>
</cffunction>
<cffunction name="reloadFramework" access="private">
<cfset local.apiRootURL = getDirectoryFromPath(cgi.script_name) />
<cfset local.apiRootURL = listDeleteAt(local.apiRootURL,listLen(local.apiRootURL,'/'),'/') />
<cfhttp method="GET" url="http://#CGI.SERVER_NAME#:#CGI.SERVER_PORT##local.apiRootURL#/index.cfm?#application._taffy.settings.reloadkey#=#application._taffy.settings.reloadPassword#" />
</cffunction>
</cfcomponent>
+10
View File
@@ -0,0 +1,10 @@
<cfsetting requesttimeout="600" />
<cfinvoke component="mxunit.runner.DirectoryTestSuite"
method="run"
directory="#expandPath('/Taffy/tests/tests')#"
componentPath="Taffy.tests.tests"
recurse="true"
returnvariable="results" />
<cfoutput> #results.getResultsOutput('extjs')# </cfoutput>
+19
View File
@@ -0,0 +1,19 @@
<cfsetting showdebugoutput="false" />
<cfscript>
testsDir = expandPath('/Taffy/tests/tests');
componentPath = 'Taffy.tests.tests';
suite = createObject('mxunit.framework.TestSuite');
files = createObject('mxunit.runner.DirectoryTestSuite').getTests(directory=testsDir, componentPath=componentPath);
for (i = 1; i <= arrayLen(files); i++){
suite.addAll(files[i]);
}
tests = suite.suites();
for (t in tests){
tests[t] = tests[t].methods;
}
</cfscript>
<cfcontent reset="true" type="application/json; charset=UTF-8" /><cfoutput>#serializeJson(tests)#</cfoutput><cfabort/>
+46
View File
@@ -0,0 +1,46 @@
<cfparam name="url.reporter" default="simple" type="variablename">
<cfset plainText = url.reporter IS "text" OR url.reporter IS "mintext">
<cfsetting requesttimeout="150" enablecfoutputonly="#plainText#">
<cfif plainText>
<cfcontent type="text/plain">
</cfif>
<strong>Test Environment</strong>:
<cfif server.coldfusion.productname contains "ColdFusion">
<cfoutput>Adobe ColdFusion #server.coldfusion.productversion#</cfoutput>
<cfelseif structKeyExists(server, "lucee")>
<cfoutput>Lucee #server.lucee.version#</cfoutput>
<cfelseif structKeyExists(server, "railo")>
<cfoutput>Railo #server.railo.version#</cfoutput>
<cfelse>
<cfoutput>#server.coldfusion.productname#</cfoutput>
</cfif>
<cfoutput> on #server.os.name# #server.os.version#</cfoutput>
<cfset system = createObject("java", "java.lang.System")>
<cfoutput> running Java #system.getProperty("java.version")#
</cfoutput>
<cfset bundles=[]>
<cfdirectory action="list" directory="#getDirectoryFromPath(getCurrentTemplatePath())#" name="files">
<cfloop query="files">
<cfif left(getFileFromPath(files.name), 4) IS "Test">
<cfset arrayAppend(bundles, "Taffy.tests.tests." & replace(getFileFromPath(files.name), ".cfc", ""))>
</cfif>
</cfloop>
<cfset r = new testbox.system.TestBox(reporter=url.reporter, bundles=bundles)>
<cfsavecontent variable="resultOutput"><cfoutput>#r.run()#</cfoutput></cfsavecontent>
<cfoutput>#trim(resultOutput)#</cfoutput>
<cfset resultObject = r.getResult()>
<cfset errors = resultObject.getTotalFail() + resultObject.getTotalError()>
<cfif errors GT 0>
<cfheader statuscode="500" statustext="Tests Failed">
</cfif>
<cfif NOT plainText>
<cfoutput>
<a href="run.cfm?ts=#GetTickCount()#">ReRun</a>
</cfoutput>
</cfif>
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB