305 lines
13 KiB
HTML
305 lines
13 KiB
HTML
|
<!doctype html>
|
||
|
<html>
|
||
|
|
||
|
<head>
|
||
|
<meta charset="utf-8">
|
||
|
<meta name="viewport" content="initial-scale=1.0">
|
||
|
<title>Assignment 7 - Tests for Tasks 1 and 2</title>
|
||
|
<link rel="stylesheet" href="qunit/qunit-2.9.2.css">
|
||
|
</head>
|
||
|
|
||
|
<body>
|
||
|
<script src="js/fetch.js"></script>
|
||
|
<script src="qunit/qunit-2.9.2.js"></script>
|
||
|
<div id="qunit"></div>
|
||
|
<div id="qunit-fixture"></div>
|
||
|
<script>
|
||
|
|
||
|
//some test payloads
|
||
|
const headers = {};
|
||
|
const baseURL = "/test/fetch";
|
||
|
const jsonURL = baseURL + "/json/ok";
|
||
|
const body = "test body as a string"
|
||
|
const jsonBody_req = {
|
||
|
json: body,
|
||
|
rnd: Math.random()
|
||
|
};
|
||
|
const jsonBody_resp = (text) => {
|
||
|
return {
|
||
|
text, body: jsonBody_req
|
||
|
}
|
||
|
}
|
||
|
|
||
|
var notValidJSON = () => {};
|
||
|
|
||
|
/*
|
||
|
* Make sure the fetch_test/router.js is installed under /test/fetch and the server is running for these tests to work
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
function testOk(f,method,url,headers,body) {
|
||
|
let msg = f.name+"('"+method+"','"+url+"','"+JSON.stringify(headers)+","+JSON.stringify(body)+") should accept the input";
|
||
|
|
||
|
return async function(assert) {
|
||
|
try {
|
||
|
await f(method,url,headers,body);
|
||
|
result = true;
|
||
|
} catch (error) {
|
||
|
console.log(msg, error);
|
||
|
msg += "\n but \n" + error;
|
||
|
result = false;
|
||
|
}
|
||
|
assert.ok(result, msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function testFail(f,method,url,headers,body) {
|
||
|
return async function(assert) {
|
||
|
try{
|
||
|
await f(method,url,headers,body);
|
||
|
result = false;
|
||
|
}
|
||
|
catch(error) {
|
||
|
result = true;
|
||
|
}
|
||
|
assert.ok(result, f.name+"("+JSON.stringify(method)+","+JSON.stringify(url)+","+JSON.stringify(headers)+","+JSON.stringify(body)+") should reject the input");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function testStatusBodyHeaders(f,method,url,headers,body,status,text,resp_headers) {
|
||
|
return async function(assert) {
|
||
|
return f(method,url,headers,body)
|
||
|
.then((res)=>{
|
||
|
assert.equal(res.status, status, method+" "+url+" should return "+status+" status code");
|
||
|
Object.keys(resp_headers).forEach((k)=>{
|
||
|
assert.ok(res.headers.has(k), method+" "+url+" response includes header "+k);
|
||
|
assert.equal(res.headers.get(k), resp_headers[k], method+" "+url+" response header "+k+" has expected value "+JSON.stringify(resp_headers[k]));
|
||
|
});
|
||
|
return res.text();
|
||
|
}).then((resp)=>{
|
||
|
assert.equal(resp, text, method+" "+url+" returns expected response body "+JSON.stringify(text));
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function testStatusBody(f,method,url,headers,body,status,text) {
|
||
|
return async function(assert) {
|
||
|
return f(method,url,headers,body)
|
||
|
.then((res)=>{
|
||
|
assert.equal(res.status, status, method+" "+url+" should return "+status+" status code");
|
||
|
return res.text();
|
||
|
}).then((resp)=>{
|
||
|
assert.equal(resp, text, method+" "+url+" returns expected response body "+JSON.stringify(text));
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function testStatusJSONBody(f,method,url,headers,body,status,json) {
|
||
|
return async function(assert) {
|
||
|
return f(method,url,headers,body)
|
||
|
.then((res)=>{
|
||
|
//assert.equal(res.status, status, method+" "+url+" should return "+status+" status code");
|
||
|
assert.deepEqual(res, json, method+" "+url+" returns expected response body "+JSON.stringify(json));
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function testStatus(f,method,url,headers,body,status,text) {
|
||
|
return async function(assert) {
|
||
|
return f(method,url,headers,body)
|
||
|
.then((res)=>{
|
||
|
assert.equal(res.status, status, method+" "+url+" should return "+status+" status code");
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function testRedirect(f,method,url,headers,body,text) {
|
||
|
return async function(assert) {
|
||
|
return f(method,url,headers,body)
|
||
|
.then((res)=>{
|
||
|
assert.ok(res.redirected, method+" "+url+" should have been redirected");
|
||
|
return res.text();
|
||
|
}).then((resp)=>{
|
||
|
assert.equal(resp, text, method+" "+url+" has expected response body after redirection "+JSON.stringify(text));
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function testAll(a){
|
||
|
return function(assert) {
|
||
|
let b = [];
|
||
|
a.forEach((f)=>{b.push(f(assert))});
|
||
|
return Promise.all(b);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
QUnit.module("Task 1: doFetchRequest Request Validation", {});
|
||
|
|
||
|
QUnit.test("reject incorrect methods", testAll(
|
||
|
[
|
||
|
testFail(doFetchRequest,"WRONG", baseURL,headers),
|
||
|
testFail(doFetchRequest,"RANDOM", baseURL,headers),
|
||
|
testFail(doFetchRequest,"",baseURL,headers),
|
||
|
testFail(doFetchRequest,undefined,baseURL,headers),
|
||
|
testFail(doFetchRequest,404,baseURL,headers)
|
||
|
]));
|
||
|
|
||
|
QUnit.test("GET, HEAD, OPTIONS, DELETE should not have a body", testAll(
|
||
|
[
|
||
|
testFail(doFetchRequest,"GET", baseURL,headers,body),
|
||
|
testFail(doFetchRequest,"HEAD", baseURL,headers,body),
|
||
|
testFail(doFetchRequest,"OPTIONS",baseURL,headers,body),
|
||
|
testFail(doFetchRequest,"DELETE",baseURL,headers,body),
|
||
|
testOk(doFetchRequest,"GET", baseURL,headers),
|
||
|
testOk(doFetchRequest,"HEAD", baseURL,headers),
|
||
|
testOk(doFetchRequest,"OPTIONS",baseURL,headers),
|
||
|
testOk(doFetchRequest,"DELETE",baseURL,headers)
|
||
|
]));
|
||
|
|
||
|
QUnit.test("POST, PUT, PATCH require the body", testAll(
|
||
|
[
|
||
|
testFail(doFetchRequest,"POST", baseURL,headers),
|
||
|
testFail(doFetchRequest,"PUT", baseURL,headers),
|
||
|
testFail(doFetchRequest,"PATCH",baseURL,headers),
|
||
|
testOk(doFetchRequest,"POST", baseURL,headers,body),
|
||
|
testOk(doFetchRequest,"PUT", baseURL,headers,body),
|
||
|
testOk(doFetchRequest,"PATCH",baseURL,headers,body)
|
||
|
]));
|
||
|
|
||
|
QUnit.test("POST, PUT, PATCH require a String body", testAll(
|
||
|
[
|
||
|
testFail(doFetchRequest,"POST", baseURL,headers,{}),
|
||
|
testFail(doFetchRequest,"PUT", baseURL,headers,{}),
|
||
|
testFail(doFetchRequest,"PATCH",baseURL,headers,{}),
|
||
|
testFail(doFetchRequest,"POST", baseURL,headers,[]),
|
||
|
testFail(doFetchRequest,"PUT", baseURL,headers,[]),
|
||
|
testFail(doFetchRequest,"PATCH",baseURL,headers,[]),
|
||
|
testFail(doFetchRequest,"POST", baseURL,headers,999),
|
||
|
testFail(doFetchRequest,"PUT", baseURL,headers,999),
|
||
|
testFail(doFetchRequest,"PATCH",baseURL,headers,999)
|
||
|
]));
|
||
|
|
||
|
QUnit.module("Task 1: doFetchRequest Response Validation", {});
|
||
|
|
||
|
QUnit.test("GET/DELETE return expected status and body", testAll(
|
||
|
[
|
||
|
testStatusBody(doFetchRequest,"GET",baseURL,{"Accept": 'text/html'},undefined,200,"GET Working"),
|
||
|
testStatus(doFetchRequest,"GET",baseURL+"/not/found",{"Accept": 'text/html'},undefined,404),
|
||
|
testStatusBody(doFetchRequest,"GET",baseURL,{"Accept": 'application/json'},undefined,200,"{\"text\":\"GET Working\"}"),
|
||
|
testStatusBody(doFetchRequest,"DELETE",baseURL,{"Accept": 'text/html'},undefined,204,"")
|
||
|
]));
|
||
|
|
||
|
QUnit.test("GET follows redirects", testAll(
|
||
|
[
|
||
|
testRedirect(doFetchRequest,"GET",baseURL+"/redirect",{"Accept": 'text/html'},undefined,"Redirect Works")
|
||
|
]));
|
||
|
|
||
|
QUnit.test("POST returns expected status, body and headers", testAll(
|
||
|
[
|
||
|
testStatusBodyHeaders(doFetchRequest,"POST",baseURL+"/new",{"Accept": 'text/html'},"X",201,"POST Working\nX",{'Location':'42'}),
|
||
|
testStatusBodyHeaders(doFetchRequest,"POST",baseURL+"/new",{"Accept": 'application/json'},"JSON",201,"{\"text\":\"POST Working\",\"body\":\"JSON\"}",{'Location':'24', 'Content-Type': 'application/json; charset=utf-8'})
|
||
|
]));
|
||
|
|
||
|
QUnit.test("PUT returns expected status, body and headers", testAll(
|
||
|
[
|
||
|
testStatusBody(doFetchRequest,"PUT",baseURL+"/echo",{"Accept": 'text/html'},"X",200,"X"),
|
||
|
testStatusBodyHeaders(doFetchRequest,"PUT",baseURL+"/echo",{"Accept": 'application/json'},"JSON",200,"{\"text\":\"PUT Working\",\"body\":\"JSON\"}",{'Content-Type': 'application/json; charset=utf-8'})
|
||
|
]));
|
||
|
|
||
|
QUnit.module("Task 2: doJSONRequest Request Validation", {});
|
||
|
|
||
|
QUnit.test("reject incorrect methods", testAll(
|
||
|
[
|
||
|
testFail(doJSONRequest,"WRONG", jsonURL,headers),
|
||
|
testFail(doJSONRequest,"RANDOM", jsonURL,headers),
|
||
|
testFail(doJSONRequest,"", jsonURL,headers),
|
||
|
testFail(doJSONRequest,undefined, jsonURL,headers),
|
||
|
testFail(doJSONRequest,404, jsonURL,headers)
|
||
|
]));
|
||
|
|
||
|
QUnit.test("GET, HEAD, OPTIONS, DELETE should not have a body", testAll(
|
||
|
[
|
||
|
testFail(doJSONRequest,"GET", jsonURL,headers,body),
|
||
|
testFail(doJSONRequest,"HEAD", jsonURL,headers,body),
|
||
|
testFail(doJSONRequest,"OPTIONS",jsonURL,headers,body),
|
||
|
testFail(doJSONRequest,"DELETE", jsonURL,headers,body),
|
||
|
testOk(doJSONRequest,"GET", jsonURL,headers),
|
||
|
//HEAD will also have an empty response body
|
||
|
//testOk(doJSONRequest,"HEAD", jsonURL,headers),
|
||
|
testOk(doJSONRequest,"OPTIONS",jsonURL,headers),
|
||
|
testOk(doJSONRequest,"DELETE", jsonURL,headers)
|
||
|
]));
|
||
|
|
||
|
QUnit.test("POST, PUT, PATCH should not have a String body", testAll(
|
||
|
[
|
||
|
testFail(doJSONRequest,"POST", jsonURL,headers,body),
|
||
|
testFail(doJSONRequest,"PUT", jsonURL,headers,body),
|
||
|
testFail(doJSONRequest,"PATCH",jsonURL,headers,body),
|
||
|
testFail(doJSONRequest,"POST", jsonURL,headers,999),
|
||
|
testFail(doJSONRequest,"PUT", jsonURL,headers,999),
|
||
|
testFail(doJSONRequest,"PATCH",jsonURL,headers,999),
|
||
|
testFail(doJSONRequest,"POST", jsonURL,headers,notValidJSON),
|
||
|
testFail(doJSONRequest,"PUT", jsonURL,headers,notValidJSON),
|
||
|
testFail(doJSONRequest,"PATCH",jsonURL,headers,notValidJSON)
|
||
|
|
||
|
]));
|
||
|
|
||
|
QUnit.test("POST, PUT, PATCH require an Object/Array body", testAll(
|
||
|
[
|
||
|
testOk(doJSONRequest,"POST", jsonURL,headers,{}),
|
||
|
testOk(doJSONRequest,"PUT", jsonURL,headers,{}),
|
||
|
testOk(doJSONRequest,"PATCH",jsonURL,headers,{}),
|
||
|
testOk(doJSONRequest,"POST", jsonURL,headers,[]),
|
||
|
testOk(doJSONRequest,"PUT", jsonURL,headers,[]),
|
||
|
testOk(doJSONRequest,"PATCH",jsonURL,headers,[])
|
||
|
]));
|
||
|
|
||
|
QUnit.test("ignore correct accept/content-type headers", testAll(
|
||
|
[
|
||
|
testOk(doJSONRequest,"POST", jsonURL,{'Accept': 'application/json'},{}),
|
||
|
testOk(doJSONRequest,"PUT", jsonURL,{'Accept': 'application/json'},{}),
|
||
|
testOk(doJSONRequest,"PATCH",jsonURL,{'Accept': 'application/json'},{}),
|
||
|
testOk(doJSONRequest,"POST", jsonURL,{'Accept': 'application/json', 'Content-Type': 'application/json'},{}),
|
||
|
testOk(doJSONRequest,"PUT", jsonURL,{'Accept': 'application/json', 'Content-Type': 'application/json'},{}),
|
||
|
testOk(doJSONRequest,"PATCH", jsonURL,{'Accept': 'application/json', 'Content-Type': 'application/json'},{}),
|
||
|
testOk(doJSONRequest,"PUT", jsonURL,{'Accept': 'application/json'},{}),
|
||
|
testOk(doJSONRequest,"PATCH",jsonURL,{'Accept': 'application/json'},{}),
|
||
|
testOk(doJSONRequest,"GET", jsonURL,{'Accept': 'application/json'}),
|
||
|
testOk(doJSONRequest,"OPTIONS", jsonURL,{'Accept': 'application/json'}),
|
||
|
testOk(doJSONRequest,"DELETE",jsonURL,{'Accept': 'application/json'})
|
||
|
]));
|
||
|
|
||
|
QUnit.test("reject incorrect accept/content-type headers", testAll(
|
||
|
[
|
||
|
testFail(doJSONRequest,"POST", jsonURL,{'Accept': 'text/plain'},{}),
|
||
|
testFail(doJSONRequest,"PUT", jsonURL,{'Accept': 'text/plain'},{}),
|
||
|
testFail(doJSONRequest,"PATCH",jsonURL,{'Accept': 'text/plain'},{}),
|
||
|
testFail(doJSONRequest,"POST", jsonURL,{'Accept': 'text/plain', 'Content-Type': 'text/plain'},{}),
|
||
|
testFail(doJSONRequest,"PUT", jsonURL,{'Accept': 'text/plain', 'Content-Type': 'text/plain'},{}),
|
||
|
testFail(doJSONRequest,"PATCH", jsonURL,{'Accept': 'text/plain', 'Content-Type': 'text/plain'},{}),
|
||
|
testFail(doJSONRequest,"PUT", jsonURL,{'Accept': 'text/plain'},{}),
|
||
|
testFail(doJSONRequest,"PATCH",jsonURL,{'Accept': 'text/plain'},{}),
|
||
|
testFail(doJSONRequest,"GET", jsonURL,{'Accept': 'text/plain'}),
|
||
|
testFail(doJSONRequest,"OPTIONS", jsonURL,{'Accept': 'text/plain'}),
|
||
|
testFail(doJSONRequest,"DELETE",jsonURL,{'Accept': 'text/plain'})
|
||
|
]));
|
||
|
|
||
|
QUnit.module("Task 2: doJSONRequest Response Validation", {});
|
||
|
|
||
|
QUnit.test("returns expected JSON body", testAll(
|
||
|
[
|
||
|
testStatusJSONBody(doJSONRequest,"PUT",baseURL+"/echo",headers,jsonBody_req,200,jsonBody_resp("PUT Working")),
|
||
|
testStatusJSONBody(doJSONRequest,"POST",baseURL+"/new",headers,jsonBody_req,201,jsonBody_resp("POST Working")),
|
||
|
testStatusJSONBody(doJSONRequest,"DELETE",baseURL,headers,undefined,204,{status: 204, text: 'DELETE Working'}),
|
||
|
testStatusJSONBody(doJSONRequest,"GET",jsonURL,headers,undefined,200,{text: 'ok'}),
|
||
|
testStatusJSONBody(doJSONRequest,"PATCH",jsonURL,headers,{},200,{text: 'ok'}),
|
||
|
testStatusJSONBody(doJSONRequest,"GET",baseURL,headers,undefined,200,{text: 'GET Working'})
|
||
|
]));
|
||
|
|
||
|
|
||
|
|
||
|
</script>
|
||
|
</body>
|
||
|
|
||
|
</html>
|