diff --git a/Gruntfile.js b/Gruntfile.js index 2bd980d..41d481b 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -36,14 +36,14 @@ module.exports = function(grunt) { bower; browserFileList.push( + "src/Environment/Browser.js", // needed because IE10 doesn't support Uint8ClampedArray // which is required by CryptoJS for typedarray support "node_modules/js-polyfills/typedarray.js", // needed because IE10 doesn't have ArrayBuffer slice "node_modules/arraybuffer-slice/index.js", // needed for IE and Safari for TextDecoder/TextEncoder - "node_modules/text-encoding/lib/encoding.js", - "src/Environment/Browser.js" + "node_modules/text-encoding/lib/encoding.js" ); nodeFileList.push( "src/Environment/Node.js" diff --git a/src/Environment/Browser.js b/src/Environment/Browser.js index 10eefa7..43870b2 100644 --- a/src/Environment/Browser.js +++ b/src/Environment/Browser.js @@ -86,6 +86,33 @@ TinCan client library }; } + // + // Add .forEach implementation for supporting our string encoding polyfill + // imported from js-polyfills to avoid bringing in the whole es5 shim + // for now, a rewrite probably moves all shims out of the main build or at + // least Environment file and leverages more of them + // + + // ES5 15.4.4.18 Array.prototype.forEach ( callbackfn [ , thisArg ] ) + // From https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach + if (!Array.prototype.forEach) { + /* jshint freeze:false,bitwise:false */ + Array.prototype.forEach = function (fun /*, thisp */) { + if (this === void 0 || this === null) { throw new TypeError(); } + + var t = Object(this); + var len = t.length >>> 0; + if (typeof fun !== "function") { throw new TypeError(); } + + var thisp = arguments[1], i; + for (i = 0; i < len; i += 1) { + if (i in t) { + fun.call(thisp, t[i], i, t); + } + } + }; + } + /* Detect CORS and XDR support */ env.hasCORS = false; env.useXDR = false; @@ -232,18 +259,6 @@ TinCan client library } if (fullRequest.length >= MAX_REQUEST_LENGTH) { - // This may change based upon what content is supported in IE Mode - if (typeof headers["Content-Type"] !== "undefined" && headers["Content-Type"] !== "application/json") { - err = new Error("Unsupported content type for IE Mode request"); - if (typeof cfg.callback !== "undefined") { - cfg.callback(err, null); - } - return { - err: err, - xhr: null - }; - } - if (typeof cfg.method === "undefined") { err = new Error("method must not be undefined for an IE Mode Request conversion"); if (typeof cfg.callback !== "undefined") { @@ -359,17 +374,6 @@ TinCan client library xhr: null }; } - if (typeof headers["Content-Type"] !== "undefined" && headers["Content-Type"] !== "application/json") { - err = new Error("Unsupported content type for IE Mode request"); - if (cfg.callback) { - cfg.callback(err, null); - return null; - } - return { - err: err, - xhr: null - }; - } // method has to go on querystring, and nothing else, // and the actual method is then always POST diff --git a/src/LRS.js b/src/LRS.js index 5c12e96..ec267de 100644 --- a/src/LRS.js +++ b/src/LRS.js @@ -1236,20 +1236,25 @@ TinCan client library ); if (typeof xhr.getResponseHeader !== "undefined" && xhr.getResponseHeader("ETag") !== null && xhr.getResponseHeader("ETag") !== "") { result.etag = xhr.getResponseHeader("ETag"); - } else { + } + else { // // either XHR didn't have getResponseHeader (probably cause it is an IE // XDomainRequest object which doesn't) or not populated by LRS so create // the hash ourselves // - result.etag = TinCan.Utils.getSHA1String(xhr.responseText); + // the LRS is responsible for quoting the Etag value so we need to mimic + // that behavior here as well + // + result.etag = "\"" + TinCan.Utils.getSHA1String(xhr.responseText) + "\""; } if (typeof xhr.contentType !== "undefined") { // most likely an XDomainRequest which has .contentType, // for the ones that it supports result.contentType = xhr.contentType; - } else if (typeof xhr.getResponseHeader !== "undefined" && xhr.getResponseHeader("Content-Type") !== null && xhr.getResponseHeader("Content-Type") !== "") { + } + else if (typeof xhr.getResponseHeader !== "undefined" && xhr.getResponseHeader("Content-Type") !== null && xhr.getResponseHeader("Content-Type") !== "") { result.contentType = xhr.getResponseHeader("Content-Type"); } @@ -1280,19 +1285,24 @@ TinCan client library ); if (typeof requestResult.xhr.getResponseHeader !== "undefined" && requestResult.xhr.getResponseHeader("ETag") !== null && requestResult.xhr.getResponseHeader("ETag") !== "") { requestResult.state.etag = requestResult.xhr.getResponseHeader("ETag"); - } else { + } + else { // // either XHR didn't have getResponseHeader (probably cause it is an IE // XDomainRequest object which doesn't) or not populated by LRS so create // the hash ourselves // - requestResult.state.etag = TinCan.Utils.getSHA1String(requestResult.xhr.responseText); + // the LRS is responsible for quoting the Etag value so we need to mimic + // that behavior here as well + // + requestResult.state.etag = "\"" + TinCan.Utils.getSHA1String(requestResult.xhr.responseText) + "\""; } if (typeof requestResult.xhr.contentType !== "undefined") { // most likely an XDomainRequest which has .contentType // for the ones that it supports requestResult.state.contentType = requestResult.xhr.contentType; - } else if (typeof requestResult.xhr.getResponseHeader !== "undefined" && requestResult.xhr.getResponseHeader("Content-Type") !== null && requestResult.xhr.getResponseHeader("Content-Type") !== "") { + } + else if (typeof requestResult.xhr.getResponseHeader !== "undefined" && requestResult.xhr.getResponseHeader("Content-Type") !== null && requestResult.xhr.getResponseHeader("Content-Type") !== "") { requestResult.state.contentType = requestResult.xhr.getResponseHeader("Content-Type"); } if (TinCan.Utils.isApplicationJSON(requestResult.state.contentType)) { @@ -1662,19 +1672,24 @@ TinCan client library ); if (typeof xhr.getResponseHeader !== "undefined" && xhr.getResponseHeader("ETag") !== null && xhr.getResponseHeader("ETag") !== "") { result.etag = xhr.getResponseHeader("ETag"); - } else { + } + else { // // either XHR didn't have getResponseHeader (probably cause it is an IE // XDomainRequest object which doesn't) or not populated by LRS so create // the hash ourselves // - result.etag = TinCan.Utils.getSHA1String(xhr.responseText); + // the LRS is responsible for quoting the Etag value so we need to mimic + // that behavior here as well + // + result.etag = "\"" + TinCan.Utils.getSHA1String(xhr.responseText) + "\""; } if (typeof xhr.contentType !== "undefined") { // most likely an XDomainRequest which has .contentType // for the ones that it supports result.contentType = xhr.contentType; - } else if (typeof xhr.getResponseHeader !== "undefined" && xhr.getResponseHeader("Content-Type") !== null && xhr.getResponseHeader("Content-Type") !== "") { + } + else if (typeof xhr.getResponseHeader !== "undefined" && xhr.getResponseHeader("Content-Type") !== null && xhr.getResponseHeader("Content-Type") !== "") { result.contentType = xhr.getResponseHeader("Content-Type"); } if (TinCan.Utils.isApplicationJSON(result.contentType)) { @@ -1705,19 +1720,24 @@ TinCan client library ); if (typeof requestResult.xhr.getResponseHeader !== "undefined" && requestResult.xhr.getResponseHeader("ETag") !== null && requestResult.xhr.getResponseHeader("ETag") !== "") { requestResult.profile.etag = requestResult.xhr.getResponseHeader("ETag"); - } else { + } + else { // // either XHR didn't have getResponseHeader (probably cause it is an IE // XDomainRequest object which doesn't) or not populated by LRS so create // the hash ourselves // - requestResult.profile.etag = TinCan.Utils.getSHA1String(requestResult.xhr.responseText); + // the LRS is responsible for quoting the Etag value so we need to mimic + // that behavior here as well + // + requestResult.profile.etag = "\"" + TinCan.Utils.getSHA1String(requestResult.xhr.responseText) + "\""; } if (typeof requestResult.xhr.contentType !== "undefined") { // most likely an XDomainRequest which has .contentType // for the ones that it supports requestResult.profile.contentType = requestResult.xhr.contentType; - } else if (typeof requestResult.xhr.getResponseHeader !== "undefined" && requestResult.xhr.getResponseHeader("Content-Type") !== null && requestResult.xhr.getResponseHeader("Content-Type") !== "") { + } + else if (typeof requestResult.xhr.getResponseHeader !== "undefined" && requestResult.xhr.getResponseHeader("Content-Type") !== null && requestResult.xhr.getResponseHeader("Content-Type") !== "") { requestResult.profile.contentType = requestResult.xhr.getResponseHeader("Content-Type"); } if (TinCan.Utils.isApplicationJSON(requestResult.profile.contentType)) { @@ -1966,19 +1986,24 @@ TinCan client library ); if (typeof xhr.getResponseHeader !== "undefined" && xhr.getResponseHeader("ETag") !== null && xhr.getResponseHeader("ETag") !== "") { result.etag = xhr.getResponseHeader("ETag"); - } else { + } + else { // // either XHR didn't have getResponseHeader (probably cause it is an IE // XDomainRequest object which doesn't) or not populated by LRS so create // the hash ourselves // - result.etag = TinCan.Utils.getSHA1String(xhr.responseText); + // the LRS is responsible for quoting the Etag value so we need to mimic + // that behavior here as well + // + result.etag = "\"" + TinCan.Utils.getSHA1String(xhr.responseText) + "\""; } if (typeof xhr.contentType !== "undefined") { // most likely an XDomainRequest which has .contentType // for the ones that it supports result.contentType = xhr.contentType; - } else if (typeof xhr.getResponseHeader !== "undefined" && xhr.getResponseHeader("Content-Type") !== null && xhr.getResponseHeader("Content-Type") !== "") { + } + else if (typeof xhr.getResponseHeader !== "undefined" && xhr.getResponseHeader("Content-Type") !== null && xhr.getResponseHeader("Content-Type") !== "") { result.contentType = xhr.getResponseHeader("Content-Type"); } if (TinCan.Utils.isApplicationJSON(result.contentType)) { @@ -2009,19 +2034,24 @@ TinCan client library ); if (typeof requestResult.xhr.getResponseHeader !== "undefined" && requestResult.xhr.getResponseHeader("ETag") !== null && requestResult.xhr.getResponseHeader("ETag") !== "") { requestResult.profile.etag = requestResult.xhr.getResponseHeader("ETag"); - } else { + } + else { // // either XHR didn't have getResponseHeader (probably cause it is an IE // XDomainRequest object which doesn't) or not populated by LRS so create // the hash ourselves // - requestResult.profile.etag = TinCan.Utils.getSHA1String(requestResult.xhr.responseText); + // the LRS is responsible for quoting the Etag value so we need to mimic + // that behavior here as well + // + requestResult.profile.etag = "\"" + TinCan.Utils.getSHA1String(requestResult.xhr.responseText) + "\""; } if (typeof requestResult.xhr.contentType !== "undefined") { // most likely an XDomainRequest which has .contentType // for the ones that it supports requestResult.profile.contentType = requestResult.xhr.contentType; - } else if (typeof requestResult.xhr.getResponseHeader !== "undefined" && requestResult.xhr.getResponseHeader("Content-Type") !== null && requestResult.xhr.getResponseHeader("Content-Type") !== "") { + } + else if (typeof requestResult.xhr.getResponseHeader !== "undefined" && requestResult.xhr.getResponseHeader("Content-Type") !== null && requestResult.xhr.getResponseHeader("Content-Type") !== "") { requestResult.profile.contentType = requestResult.xhr.getResponseHeader("Content-Type"); } if (TinCan.Utils.isApplicationJSON(requestResult.profile.contentType)) { diff --git a/test/js/BrowserPrep.js b/test/js/BrowserPrep.js index cf3e632..9335920 100644 --- a/test/js/BrowserPrep.js +++ b/test/js/BrowserPrep.js @@ -71,4 +71,14 @@ var TinCanTest, }; TinCanTest.testAttachments = true; + + // + // can't support attachments with content in browsers that don't support + // an XHR2 implementation, essentially IE < 10, so set a flag to skip + // testing related functionality + // + if (! ("withCredentials" in new XMLHttpRequest())) { + TinCanTest.testAttachments = false; + alert("Not testing attachments with content"); + } }()); diff --git a/test/js/unit/Activity.js b/test/js/unit/Activity.js index e87e82c..43bc40f 100644 --- a/test/js/unit/Activity.js +++ b/test/js/unit/Activity.js @@ -90,12 +90,16 @@ name: "activity with definition (raw definition)", instanceConfig: { id: "http://TestActivity", - definition: { name: "Test" } + definition: { + name: { + en: "Test" + } + } }, - toString: (new TinCan.ActivityDefinition({ name: "Test" })).toString(), + toString: (new TinCan.ActivityDefinition({ name: { en: "Test" } })).toString(), checkProps: { id: "http://TestActivity", - definition: new TinCan.ActivityDefinition({ name: "Test" }) + definition: new TinCan.ActivityDefinition({ name: { en: "Test" } }) } } ], diff --git a/test/js/unit/Attachment.js b/test/js/unit/Attachment.js index 7c3b47b..5c2b3ef 100644 --- a/test/js/unit/Attachment.js +++ b/test/js/unit/Attachment.js @@ -135,34 +135,39 @@ checkProps: { fileUrl: "http://id.tincanapi.com/attachment/test-attachment.pdf" } - }, - { - name: "Attachment with string content", - instanceConfig: { - content: "test text content" - }, - checkProps: { - sha2: "889f4b4a820461e25c2431acab679831f7eed2fc25f42a809769045527e7a73b", - length: 17, - content: TinCan.Utils.stringToArrayBuffer("test text content") - } - }, - { - name: "Attachment with binary content", - instanceConfig: { - content: TinCan.Utils.stringToArrayBuffer("test text content") - }, - checkProps: { - sha2: "889f4b4a820461e25c2431acab679831f7eed2fc25f42a809769045527e7a73b", - length: 17, - content: TinCan.Utils.stringToArrayBuffer("test text content") - } } ], i, obj, result; + if (TinCanTest.testAttachments) { + set.push( + { + name: "Attachment with string content", + instanceConfig: { + content: "test text content" + }, + checkProps: { + sha2: "889f4b4a820461e25c2431acab679831f7eed2fc25f42a809769045527e7a73b", + length: 17, + content: TinCan.Utils.stringToArrayBuffer("test text content") + } + }, + { + name: "Attachment with binary content", + instanceConfig: { + content: TinCan.Utils.stringToArrayBuffer("test text content") + }, + checkProps: { + sha2: "889f4b4a820461e25c2431acab679831f7eed2fc25f42a809769045527e7a73b", + length: 17, + content: TinCan.Utils.stringToArrayBuffer("test text content") + } + } + ); + } + for (i = 0; i < set.length; i += 1) { row = set[i]; obj = new TinCan.Attachment(row.instanceConfig); diff --git a/test/js/unit/LRS-browser.js b/test/js/unit/LRS-browser.js index 4359886..0c1b959 100644 --- a/test/js/unit/LRS-browser.js +++ b/test/js/unit/LRS-browser.js @@ -99,12 +99,12 @@ { agent: new TinCan.Agent(stCfg.actor), activity: { - id: "testId" + id: stCfg.target.id }, callback: function (err, xhr) { start(); - ok(err !== null, "saveState request was denied"); - ok(xhr === null, "saveState request did not return an XHR as no request was made"); + ok(err === null, "saveState request was successful"); + ok((xhr.status === 204 || (typeof XDomainRequest !== "undefined" && (xhr.status === 1223 || typeof xhr.status === "undefined"))), "xhr received 204"); } } ); @@ -221,9 +221,6 @@ // Integration testing: test common LRS functionality with an LRS // configuration that will trigger an IE Mode conversion automatically - // - saveStatement is expected to work as this library supports application/json for post requests - // - saveState is expected to fail as application/octet-stream is unsupported - // these semantics may change as other content types become supported for (i = 0; i < versions.length; i += 1) { if (TinCanTestCfg.recordStores[versions[i]]) { lrs = new TinCan.LRS(TinCanTestCfg.recordStores[versions[i]]); diff --git a/test/js/unit/LRS.js b/test/js/unit/LRS.js index ba22870..c49c2ce 100644 --- a/test/js/unit/LRS.js +++ b/test/js/unit/LRS.js @@ -198,7 +198,15 @@ list = [], seen = {}, noDupe = true, - lrs = new TinCan.LRS({ endpoint: endpoint }); + lrs; + + for (i = 0; i < versions.length; i += 1) { + if (typeof TinCanTestCfg.recordStores[versions[i]] !== "undefined") { + lrs = new TinCan.LRS(TinCanTestCfg.recordStores[versions[i]]); + break; + } + } + for (i = 0; i < 500; i += 1) { val = lrs._getBoundary(); ok(re.test(val), "formatted correctly: " + i); @@ -373,6 +381,8 @@ TinCanTest.assertHttpRequestType(result, "dropState (all) callback result is xhr" + postFix); if (err === null) { + stop(); + // // since we deleted everything this should be empty // @@ -385,79 +395,83 @@ ok(err === null, "retrieveStateIds (empty) callback err is null" + postFix); deepEqual(result, [], "retrieveStateIds (empty) callback result is empty array" + postFix); - // - // now populate a state value and verify we can get a list of one, - // and get the individual value itself - // - lrs.saveState( - documents[0].id, - documents[0].contents, - { - agent: agent, - activity: activity, - contentType: documents[0].contentType, - callback: function (err, result) { - start(); - ok(err === null, "saveState (0) callback err is null" + postFix); - TinCanTest.assertHttpRequestType(result, "saveState (0) callback result is xhr" + postFix); - - if (err === null) { - // - // make sure we get back the list with a single value - // - lrs.retrieveStateIds( - { - agent: agent, - activity: activity, - callback: function (err, result) { - start(); - ok(err === null, "retrieveStateIds (1) callback err is null" + postFix); - deepEqual(result, [documents[0].id], "retrieveStateIds (1) callback result array" + postFix); - - // - // make sure we can get the state value back - // - lrs.retrieveState( - documents[0].id, - { - agent: agent, - activity: activity, - callback: function (err, result) { - start(); - - // - // some LRSs (Cloud in particular our Travis resource) may return capital letters - // in the hash, so lowercase the received one to improve odds it matches ours - // - if (err === null) { - result.etag = result.etag.toLowerCase(); + if (err === null) { + stop(); + + // + // now populate a state value and verify we can get a list of one, + // and get the individual value itself + // + lrs.saveState( + documents[0].id, + documents[0].contents, + { + agent: agent, + activity: activity, + contentType: documents[0].contentType, + callback: function (err, result) { + start(); + ok(err === null, "saveState (0) callback err is null" + postFix); + TinCanTest.assertHttpRequestType(result, "saveState (0) callback result is xhr" + postFix); + + if (err === null) { + stop(); + + // + // make sure we get back the list with a single value + // + lrs.retrieveStateIds( + { + agent: agent, + activity: activity, + callback: function (err, result) { + start(); + ok(err === null, "retrieveStateIds (1) callback err is null" + postFix); + deepEqual(result, [documents[0].id], "retrieveStateIds (1) callback result array" + postFix); + + if (err === null) { + stop(); + + // + // make sure we can get the state value back + // + lrs.retrieveState( + documents[0].id, + { + agent: agent, + activity: activity, + callback: function (err, result) { + start(); + + // + // some LRSs (Cloud in particular our Travis resource) may return capital letters + // in the hash, so lowercase the received one to improve odds it matches ours + // + if (err === null) { + result.etag = result.etag.toLowerCase(); + } + + ok(err === null, "retrieveState (0) callback err is null" + postFix); + deepEqual( + result, + new TinCan.State(documents[0]), + "retrieveState (0) callback result is verified" + postFix + ); + } } - - ok(err === null, "retrieveState (0) callback err is null" + postFix); - deepEqual( - result, - new TinCan.State(documents[0]), - "retrieveState (0) callback result is verified" + postFix - ); - - //stop(); - } + ); } - ); - stop(); + } } - } - ); + ); + } } - stop(); } - } - ); - stop(); + ); + } } } ); - stop(); } } } @@ -730,6 +744,17 @@ asyncTest( "asyncActivityTest: " + v, function () { + // skip check for 0.9 when in XDomainRequest land because at least on + // Rustici LRSs we don't support getting back the Activity from only + // the id passed in, and in IE 8+9 the fakeStatus results in a 400 + // instead of a 404 which is what our library uses to trigger setting + // the Activity automatically to pass this check + if (typeof XDomainRequest !== "undefined" && v === "0.9") { + start(); + expect(0); + return; + } + var postFix = " (" + v + ")", lrs = session[v], activity = new TinCan.Activity( diff --git a/test/js/unit/Statement.js b/test/js/unit/Statement.js index 2bf22af..9bfced7 100644 --- a/test/js/unit/Statement.js +++ b/test/js/unit/Statement.js @@ -228,14 +228,16 @@ ); ok(st.hasAttachmentWithContent() === false, "attachment without content"); - st = new TinCan.Statement( - { - attachments: [ - new TinCan.Attachment({ content: "some content" }) - ] - } - ); - ok(st.hasAttachmentWithContent() === true, "attachment with content"); + if (TinCanTest.testAttachments) { + st = new TinCan.Statement( + { + attachments: [ + new TinCan.Attachment({ content: "some content" }) + ] + } + ); + ok(st.hasAttachmentWithContent() === true, "attachment with content"); + } } ); }()); diff --git a/test/js/unit/TinCan-sync.js b/test/js/unit/TinCan-sync.js index d4a5b57..1694a21 100644 --- a/test/js/unit/TinCan-sync.js +++ b/test/js/unit/TinCan-sync.js @@ -332,19 +332,6 @@ setResult = session[v].setState(key, val, options); - if (! NATIVE_CORS) { - deepEqual( - setResult, - { - xhr: null, - err: new Error("Unsupported content type for IE Mode request") - }, - "setResult when using XDomainRequest" - ); - - return; - } - ok(setResult.hasOwnProperty("err"), "setResult has property: err (" + v + ")"); ok(setResult.hasOwnProperty("xhr"), "setResult has property: xhr (" + v + ")"); ok(setResult.err === null, "setResult.err is null"); @@ -353,7 +340,13 @@ ok(getResult.hasOwnProperty("state"), "getResult has property: state (" + v + ")"); ok(getResult.state instanceof TinCan.State, "getResult state property is TinCan.State (" + v + ")"); deepEqual(getResult.state.contents, val, "getResult state property contents (" + v + ")"); - deepEqual(TinCan.Utils.getContentTypeFromHeader(getResult.state.contentType), "application/octet-stream", "getResult state property contentType (" + v + ")"); + deepEqual( + TinCan.Utils.getContentTypeFromHeader(getResult.state.contentType), + + // XDomainRequest can't handle some headers + (NATIVE_CORS ? "application/octet-stream" : "text/plain"), + "getResult state property contentType (" + v + ")" + ); // // reset the state to make sure we test the concurrency handling @@ -550,18 +543,6 @@ }; setResult = session[v].setActivityProfile(key, val, options); - if (! NATIVE_CORS) { - deepEqual( - setResult, - { - xhr: null, - err: new Error("Unsupported content type for IE Mode request") - }, - "setResult when using XDomainRequest" - ); - - return; - } ok(setResult.hasOwnProperty("err"), "setResult has property: err (" + v + ")"); ok(setResult.hasOwnProperty("xhr"), "setResult has property: xhr (" + v + ")"); @@ -570,7 +551,13 @@ ok(getResult.hasOwnProperty("profile"), "getResult has property: profile (" + v + ")"); ok(getResult.profile instanceof TinCan.ActivityProfile, "getResult profile property is TinCan.ActivityProfile (" + v + ")"); deepEqual(getResult.profile.contents, val, "getResult profile property contents (" + v + ")"); - deepEqual(TinCan.Utils.getContentTypeFromHeader(getResult.profile.contentType), "application/octet-stream", "getResult profile property contentType (" + v + ")"); + deepEqual( + TinCan.Utils.getContentTypeFromHeader(getResult.profile.contentType), + + // XDomainRequest can't handle some headers + (NATIVE_CORS ? "application/octet-stream" : "text/plain"), + "getResult profile property contentType (" + v + ")" + ); setResult = session[v].setActivityProfile(key, val + 1, options); @@ -760,18 +747,6 @@ }; setResult = session[v].setAgentProfile(key, val, options); - if (! NATIVE_CORS) { - deepEqual( - setResult, - { - xhr: null, - err: new Error("Unsupported content type for IE Mode request") - }, - "setResult when using XDomainRequest" - ); - - return; - } ok(setResult.hasOwnProperty("err"), "setResult has property: err (" + v + ")"); ok(setResult.hasOwnProperty("xhr"), "setResult has property: xhr (" + v + ")"); @@ -780,7 +755,13 @@ ok(getResult.hasOwnProperty("profile"), "getResult has property: profile (" + v + ")"); ok(getResult.profile instanceof TinCan.AgentProfile, "getResult profile property is TinCan.AgentProfile (" + v + ")"); deepEqual(getResult.profile.contents, val, "getResult profile property contents (" + v + ")"); - deepEqual(TinCan.Utils.getContentTypeFromHeader(getResult.profile.contentType), "application/octet-stream", "getResult profile property contentType (" + v + ")"); + deepEqual( + TinCan.Utils.getContentTypeFromHeader(getResult.profile.contentType), + + // XDomainRequest can't handle some headers + (NATIVE_CORS ? "application/octet-stream" : "text/plain"), + "getResult profile property contentType (" + v + ")" + ); setResult = session[v].setAgentProfile(key, val + 1, options); diff --git a/test/js/unit/Utils.js b/test/js/unit/Utils.js index b26c599..cbb72ec 100644 --- a/test/js/unit/Utils.js +++ b/test/js/unit/Utils.js @@ -76,19 +76,22 @@ ok(TinCan.Utils.getSHA1String("test") === "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", "return value"); } ); - test( - "getSHA256String", - function () { - var str = "test", - strAB = TinCan.Utils.stringToArrayBuffer(str); - ok(TinCan.Utils.getSHA256String(str) === "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", "string content return value"); + if (TinCanTest.testAttachments) { + test( + "getSHA256String", + function () { + var str = "test", + strAB = TinCan.Utils.stringToArrayBuffer(str); + + ok(TinCan.Utils.getSHA256String(str) === "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", "string content return value"); - if (Object.prototype.toString.call(strAB) === "[object ArrayBuffer]") { - ok(TinCan.Utils.getSHA256String(strAB) === "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", "array buffer content return value"); + if (Object.prototype.toString.call(strAB) === "[object ArrayBuffer]") { + ok(TinCan.Utils.getSHA256String(strAB) === "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08", "array buffer content return value"); + } } - } - ); + ); + } test( "getBase64String", function () { @@ -98,7 +101,15 @@ test( "parseURL", function () { - var result; + var result, + handleUndefined = undefined; + + // check to see if this browser splices undefined normally + // cause IE 8 doesn't + match = "someString".match(/(.+)(?::([0-9]+))?/); + if (match[2] === "") { + handleUndefined = ""; + } result = TinCan.Utils.parseURL("http://tincanapi.com"); deepEqual( @@ -107,7 +118,7 @@ protocol: "http:", host: "tincanapi.com", hostname: "tincanapi.com", - port: undefined, + port: handleUndefined, pathname: "/", search: "", hash: "", @@ -124,7 +135,7 @@ protocol: "https:", host: "tincanapi.com", hostname: "tincanapi.com", - port: undefined, + port: handleUndefined, pathname: "/", search: "", hash: "", @@ -141,7 +152,7 @@ protocol: "http:", host: "tincanapi.com", hostname: "tincanapi.com", - port: undefined, + port: handleUndefined, pathname: "/", search: "", hash: "", @@ -158,7 +169,7 @@ protocol: "https:", host: "tincanapi.com", hostname: "tincanapi.com", - port: undefined, + port: handleUndefined, pathname: "/", search: "", hash: "", @@ -175,7 +186,7 @@ protocol: "https:", host: "tincanapi.com", hostname: "tincanapi.com", - port: undefined, + port: handleUndefined, pathname: "/TinCanJS", search: "", hash: "", @@ -192,7 +203,7 @@ protocol: "https:", host: "tincanapi.com", hostname: "tincanapi.com", - port: undefined, + port: handleUndefined, pathname: "/TinCanJS/", search: "", hash: "", @@ -209,7 +220,7 @@ protocol: "http:", host: "localhost", hostname: "localhost", - port: undefined, + port: handleUndefined, pathname: "/", search: "", hash: "", @@ -226,7 +237,7 @@ protocol: "http:", host: "localhost", hostname: "localhost", - port: undefined, + port: handleUndefined, pathname: "/TinCanJS/Test", search: "", hash: "", @@ -280,7 +291,7 @@ protocol: "https:", host: "tincanapi.com", hostname: "tincanapi.com", - port: undefined, + port: handleUndefined, pathname: "/TinCanJS/Test/TinCan.Utils_parseURL/test", search: "?paramA=1¶mB=2&weirdParam=odd?secondQuestionMark", hash: "#withHash",