| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <title>app:URI compliance tests</title> | |
| <script src='resources/testharness.js'></script> | |
| <script src='resources/testharnessreport.js'></script> | |
| <link rel='stylesheet' href='resource/testharness.css'> | |
| <link rel="help" href="http://app-uri.sysapps.org/" data-tested-assertations="following::OL[1]/LI[2]" /> | |
| <style> | |
| div {padding:5px 5px 10px 5px;} | |
| </style> | |
| </head> | |
| <body> | |
| <div id="logs"></div> | |
| <div id="log"></div> | |
| <script> | |
| /********************************************************************************************** | |
| * This test suite checks your implementation for compliance with the app-URI specification * | |
| **********************************************************************************************/ | |
| /* Check if protocol is "app" */ | |
| if (window.location.protocol === "app:") { | |
| /* Logging current domain */ | |
| var domain = window.location.protocol + "//" + window.location.host + "/"; | |
| document.getElementById("logs").innerHTML = "Current domain: " + domain; | |
| /* Function that will change HOST value if it is equal to currect application host */ | |
| function ChangeHostIfEqCurrent(URI){ | |
| /* Check if URI host is NOT the same as current application host */ | |
| if (URI.substring(6, 35) === window.location.host) { | |
| if (URI.substring(6, 7) !== 4) | |
| URI = URI.replace(URI.substring(6, 7), "4"); | |
| else | |
| URI = URI.replace(URI.substring(6, 7), "5"); | |
| } | |
| return URI; | |
| } | |
| /******************************************************** | |
| * 6.1 Synthesizing an app: URI | |
| * | |
| * link: http://app-uri.sysapps.org/#synthesizing | |
| * | |
| ********************************************************/ | |
| /** | |
| * Syntax-Based Normalization | |
| * | |
| * rules for dereferencing an app: URI => 3. Let URI be the value of the [HTTP] Request URI. | |
| */ | |
| var TC_name = "Test: Synthesizing an app:URI. Syntax-Based Normalization"; | |
| // variable needed to test scheme-based normalization | |
| var tmp_domain = window.location.protocol + "//" + window.location.host; | |
| var CaseNormalizationXHRtests = [ /* scheme: [ TC name, URI] */ | |
| [TC_name + " XHR full path: {} => %7b%7d", | |
| domain + 'resources/ExamPLE/%7bmY%7d/z...z/index.html'], | |
| [TC_name + " XHR full path: } => %7D", | |
| domain + 'resources/ExamPLE/%7bmY%7D/z...z/index.html'], | |
| [TC_name + " XHR full path: {} => %7B%7D", | |
| domain + 'resources/ExamPLE/%7BmY%7D/z...z/index.html'], | |
| [TC_name + " XHR full path: Capital letters in patch", | |
| domain + 'resources/ExamPLE/mmY/index.html'], | |
| [TC_name + " XHR relative path: {} => %7b%7d", | |
| 'resources/ExamPLE/%7bmY%7d/z...z/index.html'], | |
| [TC_name + " XHR relative path: } => %7D", | |
| 'resources/ExamPLE/%7bmY%7D/z...z/index.html'], | |
| [TC_name + " XHR relative path: P. => %50%2e", | |
| 'resources/Exam%50LE/%7bmY%7d/z%2e..z/index.html'], | |
| [TC_name + " XHR relative path: Capital letters in patch", | |
| 'resources/ExamPLE/mmY/index.html'], | |
| [TC_name + " XHR relative path: ~ => ~", | |
| 'resources/ImaGes/~t/{!a}/~sth.png'], | |
| [TC_name + " XHR relative path: ~{} => ~%7b%7d", | |
| 'resources/ImaGes/~t/%7b!a%7d/~sth.png'], | |
| /* Percent-Encoding Normalization*/ | |
| [TC_name + " Percent-Encoding Normalization - XHR full path: c. => %63%2e", | |
| domain + 'resources/ExamPLE/%7bmY%7d/z%2e..z/index.html'], | |
| [TC_name + " Percent-Encoding Normalization - XHR full path: P. => %50%2e", | |
| domain + 'resources/Exam%50LE/%7bmY%7d/z%2e..z/index.html'], | |
| [TC_name + " Percent-Encoding Normalization - XHR relative path: {} => %7B%7D", | |
| 'resources/ExamPLE/%7BmY%7D/z...z/index.html'], | |
| [TC_name + " Percent-Encoding Normalization - XHR relative path: c. => %63%2e", | |
| 'resources/ExamPLE/%7bmY%7d/z%2e..z/index.html'], | |
| [TC_name + " XHR relative path: ~{} => ~%7b%7d", | |
| 'resources/ImaGes/~t/%7b!a%7d/~sth.png'], | |
| /* Path Segment Normalization */ | |
| [TC_name + " Path Segment Normalization: using '../..' in path ", | |
| 'resources/ExamPLE/mmY/../../ImaGes/~t/%7b!a%7d/~sth.png'], | |
| /* Scheme-Based Normalization */ | |
| [TC_name + " Scheme-Based Normalization: domain:/", | |
| tmp_domain + ':/resources/ImaGes/~t/%7b!a%7d/~sth.png'] | |
| ]; | |
| CaseNormalizationXHRtests.forEach(function (data, i) { | |
| var name = data[0]; | |
| var URI = data[1]; | |
| var xhrTest = async_test(name + " [case " + i + "]"); | |
| var xhr; | |
| xhrTest.step(function () { | |
| xhr = new XMLHttpRequest(); | |
| xhr.open("GET", URI, true); | |
| xhr.onreadystatechange = xhrTest.step_func(function (ev) { | |
| if (xhr.readyState === 4 && xhr.status === 200) { | |
| assert_true(true); | |
| xhrTest.done(); | |
| } | |
| if (xhr.readyState !== 4 && xhr.status !== 200 && xhr.status !== 0) { | |
| assert_true(false, | |
| "[ Error: readyState=" + xhr.readyState + " satus=" + xhr.status + "] "); | |
| } | |
| }); | |
| xhr.send(); | |
| }); | |
| delete name, URI, xhr, xhrTest; | |
| }); | |
| delete CaseNormalizationXHRtests; | |
| /** | |
| * ContentType response | |
| * | |
| * rules for dereferencing an app: URI => | |
| 8. Let potential-file be the result of attempting locate the file at path | |
| */ | |
| TC_name = "Test: [HTTP] 200 response status (OK),value of content-type as the [HTTP] "; | |
| TC_name += "Content-Type header, and the contents of potential-file as the response body"; | |
| var ContentTypeResponsetests = [ /* scheme:[ TC name, URI, content-type] */ | |
| [TC_name + ' [text/html]', 'resources/ExamPLE/mmY/index.html', 'text/html'], | |
| [TC_name + " [image/png]", 'resources/ImaGes/~t/%7b!a%7d/~sth.png', "image/png"], | |
| [TC_name + " [text/plain]", 'resources/ExamPLE/mmY/sth.txt', "text/plain"] | |
| ]; | |
| ContentTypeResponsetests.forEach(function (data, i) { | |
| var name = data[0]; | |
| var URI = data[1]; | |
| var content_type = data[2]; | |
| var xhrTest = async_test(name + " [case " + i + "]"); | |
| var xhr; | |
| xhrTest.step(function () { | |
| xhr = new XMLHttpRequest(); | |
| xhr.open("GET", URI, true); | |
| xhr.onreadystatechange = xhrTest.step_func(function (ev) { | |
| if (xhr.readyState === 4 && xhr.status === 200) { | |
| assert_true(xhr.getResponseHeader("Content-Type") === content_type, | |
| "[Content-Type does not mach with expected, it is: " | |
| + xhr.getResponseHeader("Content-Type") + "]"); | |
| xhrTest.done(); | |
| } | |
| if (xhr.readyState !== 4 && xhr.status !== 200 && xhr.status !== 0) { | |
| assert_true(false, | |
| "[ Error: readyState=" + xhr.readyState + " satus=" + xhr.status + "] "); | |
| } | |
| }); | |
| xhr.send(); | |
| }); | |
| delete name, URI, xhr, xhrTest, content_type; | |
| }); | |
| delete ContentTypeResponsetests; | |
| /** | |
| * Case Normalization in Path | |
| * | |
| * rules for dereferencing an app: URI => | |
| 4. Resolve URI into an absolute URL using the document's origin as the base. | |
| * rules for dereferencing an app: URI => 7. Let path be the path component of URI. | |
| * | |
| * Character Normalization in domain name | |
| */ | |
| TC_name = "Test: Synthesizing an app:URI. Syntax-Based Normalization: Case Normalization"; | |
| var PathCaseNormalizationtests = [ /* scheme: [ TC name, URI] */ | |
| [TC_name, "resources/ImaGes/{{a}}/Test_1/$a/sth34!.png", | |
| domain + "resources/ImaGes/%7B%7Ba%7D%7D/Test_1/$a/sth34!.png", true], | |
| [TC_name, "resources/ImaGes/{{a}}/Test_1/$a/sth34!.png", | |
| domain + "resources/ImaGes/%7b%7Ba%7D%7D/Test_1/$a/sth34!.png", false], | |
| /* Character Normalization in Domain */ | |
| [TC_name, window.location.protocol + "//" + window.location.host.toUpperCase() | |
| + "/resources/ImaGes/{{a}}/Test_1/$a/sth34!.png", | |
| domain + "resources/ImaGes/%7B%7Ba%7D%7D/Test_1/$a/sth34!.png", true] | |
| ]; | |
| PathCaseNormalizationtests.forEach(function (data, i) { | |
| var name = data[0]; | |
| var elem_path = data[1]; | |
| var path_expected = data[2]; | |
| var expected = data[3]; | |
| test(function () { | |
| var img = document.createElement("img"); | |
| img.src = elem_path; | |
| if (expected) | |
| assert_true(img.src === path_expected, | |
| "[Error, path=" + img.src + " Expected=" + domain + path_expected + "]"); | |
| else | |
| assert_false(img.src === path_expected, | |
| "[Error, path=" + img.src + " Expected=" + domain + path_expected + "]"); | |
| delete img; | |
| }, name + " [case " + i + "]"); | |
| delete elem_path, path_expected, expected, name; | |
| }); | |
| delete PathCaseNormalizationtests; | |
| /******************************************************************************************** | |
| * 6.4 Dereferencing and retrieval of files from a container | |
| * | |
| * link: http://app-uri.sysapps.org/#dereferencing-and-retrieval-of-files-from-a-container | |
| * | |
| ********************************************************************************************/ | |
| /** | |
| * 501 Method Not Implemented error - response body MUST be empty | |
| * | |
| * rules for dereferencing an app: URI => | |
| 1. If the request is not a [HTTP] GET request, | |
| return a [HTTP] 501 Not Implemented response and terminate this algorithm. | |
| */ | |
| function Get_501_reponse(name, URI, expected_response) { | |
| var xhrTest = async_test(name); | |
| xhrTest.step(function () { | |
| var xhr = new XMLHttpRequest(); | |
| /* on purpose wrong method "gett" instead of "get" was used */ | |
| xhr.open("gett", URI, true); | |
| xhr.onreadystatechange = xhrTest.step_func(function (ev) { | |
| if (xhr.readyState !== 4 && xhr.status === 501) { | |
| assert_true(xhr.response === expected_response, | |
| "[" + xhr.status + " error, response:[" + xhr.response + "] " + "]"); | |
| xhrTest.done(); | |
| } | |
| if (xhr.readyState === 4 && xhr.status === 200) { | |
| assert_true(false, | |
| "[Should get 501 but got 200 OK, " | |
| +"file found while it should not find it, " | |
| +" non existing 'gett' method used"); | |
| } | |
| }); | |
| xhr.send(); | |
| }); | |
| delete xhrTest; | |
| } | |
| Get_501_reponse(TC_name + " 501 Method Not Implemented error expected", | |
| 'resources/ExamPLE/mmY/index.html', ""); | |
| /** | |
| * 400 Bad Request error - response body MUST be empty | |
| * | |
| * rules for dereferencing an app: URI => | |
| 5. If the URI does not conform to the appuri ABNF, return a | |
| [HTTP] 400 Bad Request response and terminate this algorithm. | |
| */ | |
| function Get_400_reponse(name, URI, expected_response) { | |
| var xhrTest = async_test(name); | |
| xhrTest.step(function () { | |
| var xhr = new XMLHttpRequest(); | |
| //alert(URI); | |
| xhr.open("GET", URI, true); | |
| xhr.onreadystatechange = xhrTest.step_func(function (ev) { | |
| if (xhr.readyState !== 4 && xhr.status === 400) { | |
| assert_true(xhr.response === expected_response, | |
| "[" + xhr.status + " error, response:[" + xhr.response + "] " + "]"); | |
| xhrTest.done(); | |
| } | |
| if (xhr.readyState === 4 && xhr.status === 200) { | |
| assert_true(false, | |
| "[Should get 400 but got 200 OK, " | |
| +"file found while it should not find it, " | |
| +"since no specific file requested]"); | |
| } | |
| }); | |
| xhr.send(); | |
| }); | |
| delete xhrTest; | |
| } | |
| Get_400_reponse(TC_name + " 400 Method Not Implemented error expected, no path", | |
| tmp_domain, ""); | |
| Get_400_reponse(TC_name + " 400 Method Not Implemented error expected, different domain with no path", | |
| ChangeHostIfEqCurrent("app://f15a6d20-cefa-13e5-1972-800e20d19a76"), ""); | |
| /** | |
| * 403 Forbidden error - response body MUST be empty | |
| * | |
| * rules for dereferencing an app: URI => | |
| 6. If the URI uses the scheme 'app', but the authority does not match | |
| the one assigned to this document, return a [HTTP] 403 Forbidden | |
| response and terminate this algorithm | |
| (i.e., prevent inter-application content access). | |
| */ | |
| function Get_403_reponse(name, URI, expected_response) { | |
| var xhrTest = async_test(name); | |
| xhrTest.step(function () { | |
| /* Change if URI host is the same as current application host */ | |
| URI = ChangeHostIfEqCurrent(URI); | |
| var xhr = new XMLHttpRequest(); | |
| xhr.open("GET", URI, true); | |
| xhr.onreadystatechange = xhrTest.step_func(function (ev) { | |
| if (xhr.readyState === 4 && xhr.status === 200) { | |
| assert_true(false, "[403 error expected, got: 200 OK instead]"); | |
| } | |
| if (xhr.readyState !== 4 && xhr.status === 403) { | |
| assert_true(xhr.response === expected_response, "[" | |
| + xhr.status + " error, response:[" + xhr.response + "] " | |
| + "]"); | |
| xhrTest.done(); | |
| } | |
| }); | |
| xhr.send(); | |
| }); | |
| } | |
| Get_403_reponse(TC_name + " Access to restricted URI - 403 Forbidden error expected", | |
| window.location.protocol + "//f15a6d20-cefa-13e5-1972-800e20d19a76/" + 'resources/ExamPLE/mmY/index.html', ""); | |
| /** | |
| * 404 Not Found error - response body MUST be empty | |
| * | |
| * rules for dereferencing an app: URI => | |
| 9. If potential-file is not found at the given path inside the container, | |
| return a [HTTP] 404 Not Found response. | |
| */ | |
| TC_name = "Test: 6.4 Dereferencing and retrieval of files from a container"; | |
| var CompareResponseBodytests = [ /* scheme: [TC name, URI, expected_response]*/ | |
| [TC_name + " 404 Not Found error expected", | |
| 'resources/ImaGes/~t/%7b!a%7d/~sth11.png', ""] | |
| ]; | |
| CompareResponseBodytests.forEach(function (data, i) { | |
| var name = data[0]; | |
| var URI = data[1]; | |
| var expected_response = data[2]; | |
| var xhrTest = async_test(name); | |
| var xhr; | |
| xhrTest.step(function () { | |
| xhr = new XMLHttpRequest(); | |
| xhr.open("GET", URI, true); | |
| xhr.onreadystatechange = xhrTest.step_func(function (ev) { | |
| if (xhr.readyState !== 4 && xhr.status === 404) { | |
| assert_true(xhr.response === expected_response, | |
| "[" + xhr.status + " error, response:[" + xhr.response + "] " + "]"); | |
| xhrTest.done(); | |
| } | |
| if (xhr.readyState === 4 && xhr.status === 200) { | |
| assert_true(false, "[404 error expected, got: 200 OK instead]"); | |
| } | |
| }); | |
| xhr.send(); | |
| }); | |
| delete xhrTest, xhr; | |
| }); | |
| delete CompareResponseBodytests; | |
| } else { | |
| document.getElementById("logs").innerHTML = | |
| "This is a test suite for app protocol only. Test aborted due to current protocol " | |
| + window.location.protocol; | |
| } | |
| </script> | |
| </body> | |
| </html> | |