Add test for HttpRequest and HttpUrl, bring classes up to spec, change how headers are passed around
This commit is contained in:
parent
6fa4249461
commit
67dd1feae8
4
.travis.yaml
Normal file
4
.travis.yaml
Normal file
|
@ -0,0 +1,4 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 0.8
|
||||
- 0.10
|
10
Gruntfile.js
10
Gruntfile.js
|
@ -1,7 +1,15 @@
|
|||
module.exports = function (grunt) {
|
||||
grunt.loadNpmTasks('grunt-karma');
|
||||
grunt.loadNpmTasks('grunt-typescript');
|
||||
|
||||
grunt.initConfig({
|
||||
karma: {
|
||||
unit: {
|
||||
configFile: "karma.conf.js",
|
||||
singleRun: true,
|
||||
browsers: ['PhantomJS']
|
||||
}
|
||||
},
|
||||
typescript: {
|
||||
base: {
|
||||
src: ["lib/**/*.ts"],
|
||||
|
@ -15,4 +23,6 @@ module.exports = function (grunt) {
|
|||
});
|
||||
|
||||
grunt.registerTask('default', ['typescript']);
|
||||
|
||||
grunt.registerTask('test', ['typescript', 'karma:unit'])
|
||||
};
|
14
build/typertext.d.ts
vendored
14
build/typertext.d.ts
vendored
|
@ -22,10 +22,10 @@ declare module Typertext {
|
|||
private headers;
|
||||
private httpStatus;
|
||||
private content;
|
||||
constructor(status: Http.HttpResponseStatus, responseHeaders?: Http.HttpHeaderData, httpResponseCode?: number, responseBody?: T);
|
||||
constructor(status: Http.HttpResponseStatus, responseHeaderGetter?: (input: string) => string, httpResponseCode?: number, responseBody?: T);
|
||||
public GetContent(): T;
|
||||
public GetContentType(): string;
|
||||
public GetHeaders(): Http.HttpHeaderData;
|
||||
public GetHeader(name: string): string;
|
||||
public GetHttpStatus(): number;
|
||||
public GetStatus(): Http.HttpResponseStatus;
|
||||
}
|
||||
|
@ -39,11 +39,6 @@ declare module Typertext.Http {
|
|||
class HttpException extends BaseException<HttpResponseStatus> {
|
||||
}
|
||||
}
|
||||
declare module Typertext.Http {
|
||||
interface HttpHeaderData {
|
||||
[index: string]: string;
|
||||
}
|
||||
}
|
||||
declare module Typertext.Http {
|
||||
enum HttpMethod {
|
||||
GET = 0,
|
||||
|
@ -68,7 +63,6 @@ declare module Typertext.Http {
|
|||
}
|
||||
declare module Typertext.Http {
|
||||
class HttpRequest implements GenericRequest<HttpResponseHandler> {
|
||||
private static parseHeaderString(headerStr);
|
||||
constructor();
|
||||
public Get(request: HttpUrl, callback: HttpResponseHandler): void;
|
||||
public Post(request: HttpUrl, postData: HttpPostData, callback: HttpResponseHandler): void;
|
||||
|
@ -77,7 +71,7 @@ declare module Typertext.Http {
|
|||
}
|
||||
declare module Typertext.Http {
|
||||
class HttpResponse extends GenericResponse<string> {
|
||||
constructor(status: HttpResponseStatus, responseHeaders?: HttpHeaderData, httpResponseCode?: number, responseBody?: string);
|
||||
constructor(status: HttpResponseStatus, responseHeaderGetter?: (input: string) => string, httpResponseCode?: number, responseBody?: string);
|
||||
}
|
||||
}
|
||||
declare module Typertext.Http {
|
||||
|
@ -135,7 +129,7 @@ declare module Typertext.Json {
|
|||
declare module Typertext.Json {
|
||||
class JsonResponse extends GenericResponse<JsonObject> {
|
||||
static fromHttpResponse(httpResponse: Http.HttpResponse): JsonResponse;
|
||||
constructor(status: Http.HttpResponseStatus, responseHeaders?: Http.HttpHeaderData, httpResponseCode?: number, responseBody?: JsonObject);
|
||||
constructor(status: Http.HttpResponseStatus, responseHeaderGetter?: (input: string) => string, httpResponseCode?: number, responseBody?: JsonObject);
|
||||
}
|
||||
}
|
||||
declare module Typertext.Json {
|
||||
|
|
|
@ -28,9 +28,9 @@ var Typertext;
|
|||
var Typertext;
|
||||
(function (Typertext) {
|
||||
var GenericResponse = (function () {
|
||||
function GenericResponse(status, responseHeaders, httpResponseCode, responseBody) {
|
||||
function GenericResponse(status, responseHeaderGetter, httpResponseCode, responseBody) {
|
||||
this.status = status;
|
||||
this.headers = responseHeaders;
|
||||
this.headers = responseHeaderGetter;
|
||||
this.httpStatus = httpResponseCode;
|
||||
this.content = responseBody;
|
||||
}
|
||||
|
@ -39,11 +39,11 @@ var Typertext;
|
|||
};
|
||||
|
||||
GenericResponse.prototype.GetContentType = function () {
|
||||
return this.GetHeaders()["Content-Type"];
|
||||
return this.GetHeader("Content-Type");
|
||||
};
|
||||
|
||||
GenericResponse.prototype.GetHeaders = function () {
|
||||
return this.headers;
|
||||
GenericResponse.prototype.GetHeader = function (name) {
|
||||
return this.headers(name);
|
||||
};
|
||||
|
||||
GenericResponse.prototype.GetHttpStatus = function () {
|
||||
|
@ -105,18 +105,6 @@ var Typertext;
|
|||
var HttpRequest = (function () {
|
||||
function HttpRequest() {
|
||||
}
|
||||
HttpRequest.parseHeaderString = function (headerStr) {
|
||||
var headers = {}, headerPairs = headerStr.split('\u000d\u000a');
|
||||
for (var i = 0; i < headerPairs.length; i++) {
|
||||
var headerPair = headerPairs[i], index = headerPair.indexOf('\u003a\u0020');
|
||||
if (index > 0) {
|
||||
var key = headerPair.substring(0, index);
|
||||
headers[key] = headerPair.substring(index + 2);
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
};
|
||||
|
||||
HttpRequest.prototype.Get = function (request, callback) {
|
||||
this.RawRequest(0 /* GET */, request, {}, callback);
|
||||
};
|
||||
|
@ -132,9 +120,11 @@ var Typertext;
|
|||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = function () {
|
||||
if (xhr.readyState == 4) {
|
||||
var headers = HttpRequest.parseHeaderString(xhr.getAllResponseHeaders());
|
||||
var getHeader = function (name) {
|
||||
return xhr.getResponseHeader(name);
|
||||
};
|
||||
if (xhr.status == 200) {
|
||||
callback(new Typertext.Http.HttpResponse(0 /* success */, headers, xhr.status, xhr.responseText));
|
||||
callback(new Typertext.Http.HttpResponse(0 /* success */, getHeader, xhr.status, xhr.responseText));
|
||||
} else if (xhr.status >= 400 && xhr.status < 500) {
|
||||
throw new Typertext.Http.HttpException("Error type is unimplemented", -1, 2 /* clientError */);
|
||||
} else if (xhr.status >= 500 && xhr.status < 600) {
|
||||
|
@ -170,8 +160,8 @@ var Typertext;
|
|||
(function (Http) {
|
||||
var HttpResponse = (function (_super) {
|
||||
__extends(HttpResponse, _super);
|
||||
function HttpResponse(status, responseHeaders, httpResponseCode, responseBody) {
|
||||
_super.call(this, status, responseHeaders, httpResponseCode, responseBody);
|
||||
function HttpResponse(status, responseHeaderGetter, httpResponseCode, responseBody) {
|
||||
_super.call(this, status, responseHeaderGetter, httpResponseCode, responseBody);
|
||||
}
|
||||
return HttpResponse;
|
||||
})(Typertext.GenericResponse);
|
||||
|
@ -218,18 +208,25 @@ var Typertext;
|
|||
this.port = port;
|
||||
}
|
||||
HttpUrl.DefaultPort = function (protocol) {
|
||||
return ((protocol == 0 /* http */) ? 80 : 443);
|
||||
switch (protocol) {
|
||||
case 0 /* http */:
|
||||
return 80;
|
||||
case 1 /* https */:
|
||||
return 443;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
HttpUrl.FromUrl = function (location) {
|
||||
var l = document.createElement("a");
|
||||
l.href = location;
|
||||
return new HttpUrl(l.hostname, Typertext.Http.HttpProtocol[l.protocol], l.pathname, HttpUrl.DecodeQueryString(l.search));
|
||||
return new HttpUrl(l.hostname, Typertext.Http.HttpProtocol[l.protocol.slice(0, -1)], l.pathname, HttpUrl.DecodeQueryString(l.search), parseInt(l.port));
|
||||
};
|
||||
|
||||
HttpUrl.DecodeQueryString = function (queryString) {
|
||||
if (queryString.length == 0 || queryString == "?") {
|
||||
return {};
|
||||
if (queryString.indexOf("?") == 0) {
|
||||
queryString = queryString.substring(1);
|
||||
}
|
||||
|
||||
return HttpUrl.UrlDecodeString(queryString);
|
||||
|
@ -254,20 +251,25 @@ var Typertext;
|
|||
HttpUrl.UrlDecodeString = function (queryString) {
|
||||
var returnValue = {}, params = HttpUrl.splitString(queryString, "&");
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var param = HttpUrl.splitString(params[i], "=", 2);
|
||||
if (param.length == 1) {
|
||||
returnValue[param[0]] = "";
|
||||
if (params[i] == "") {
|
||||
continue;
|
||||
}
|
||||
|
||||
returnValue[param[0]] = param[1];
|
||||
var param = HttpUrl.splitString(params[i], "=", 2);
|
||||
var key = decodeURIComponent(param[0]);
|
||||
if (param.length == 1) {
|
||||
returnValue[key] = "";
|
||||
continue;
|
||||
}
|
||||
|
||||
returnValue[key] = decodeURIComponent(param[1]);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
};
|
||||
|
||||
HttpUrl.splitString = function (input, separator, limit) {
|
||||
if (typeof limit === "undefined") { limit = 0; }
|
||||
if (typeof limit === "undefined") { limit = -1; }
|
||||
limit++;
|
||||
var chunks = input.split(separator);
|
||||
if (limit > 0 && chunks.length > limit) {
|
||||
|
@ -352,11 +354,11 @@ var Typertext;
|
|||
(function (Json) {
|
||||
var JsonResponse = (function (_super) {
|
||||
__extends(JsonResponse, _super);
|
||||
function JsonResponse(status, responseHeaders, httpResponseCode, responseBody) {
|
||||
_super.call(this, status, responseHeaders, httpResponseCode, responseBody);
|
||||
function JsonResponse(status, responseHeaderGetter, httpResponseCode, responseBody) {
|
||||
_super.call(this, status, responseHeaderGetter, httpResponseCode, responseBody);
|
||||
}
|
||||
JsonResponse.fromHttpResponse = function (httpResponse) {
|
||||
return new JsonResponse(httpResponse.GetStatus(), httpResponse.GetHeaders(), httpResponse.GetHttpStatus(), window["JSON"].parse(httpResponse.GetContent()));
|
||||
return new JsonResponse(httpResponse.GetStatus(), httpResponse.GetHeader, httpResponse.GetHttpStatus(), window["JSON"].parse(httpResponse.GetContent()));
|
||||
};
|
||||
return JsonResponse;
|
||||
})(Typertext.GenericResponse);
|
||||
|
|
File diff suppressed because one or more lines are too long
10
karma.conf.js
Normal file
10
karma.conf.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: __dirname,
|
||||
frameworks: ['jasmine'],
|
||||
files: [
|
||||
'test/**/*.test.js',
|
||||
'build/typertext.js'
|
||||
]
|
||||
});
|
||||
};
|
|
@ -4,12 +4,11 @@
|
|||
* @submodule Json
|
||||
*/
|
||||
module Typertext {
|
||||
import HttpHeaderData = Typertext.Http.HttpHeaderData;
|
||||
import HttpResponseStatus = Typertext.Http.HttpResponseStatus;
|
||||
|
||||
export class GenericResponse<T> {
|
||||
private status:HttpResponseStatus;
|
||||
private headers:HttpHeaderData;
|
||||
private headers:(input:string)=>string;
|
||||
private httpStatus:number;
|
||||
private content:T;
|
||||
|
||||
|
@ -21,7 +20,7 @@ module Typertext {
|
|||
* @uses Typertext.Http.HttpResponseStatus
|
||||
*
|
||||
* @param {HttpResponseStatus} status
|
||||
* @param {HttpHeaderData} responseHeaders
|
||||
* @param {Function} responseHeaderGetter
|
||||
* @param {number} httpResponseCode
|
||||
* @param {T} responseBody
|
||||
* @constructor
|
||||
|
@ -29,9 +28,9 @@ module Typertext {
|
|||
* @author Kegan Myers <kegan@keganmyers.com>
|
||||
* @version 0.3.0
|
||||
*/
|
||||
constructor(status:HttpResponseStatus, responseHeaders?:HttpHeaderData, httpResponseCode?:number, responseBody?:T) {
|
||||
constructor(status:HttpResponseStatus, responseHeaderGetter?:(input:string)=>string, httpResponseCode?:number, responseBody?:T) {
|
||||
this.status = status;
|
||||
this.headers = responseHeaders;
|
||||
this.headers = responseHeaderGetter;
|
||||
this.httpStatus = httpResponseCode;
|
||||
this.content = responseBody;
|
||||
}
|
||||
|
@ -52,17 +51,17 @@ module Typertext {
|
|||
* @constructor
|
||||
*/
|
||||
public GetContentType():string {
|
||||
return this.GetHeaders()["Content-Type"];
|
||||
return this.GetHeader("Content-Type");
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessor method
|
||||
*
|
||||
* @returns {HttpHeaderData}
|
||||
* @returns {string}
|
||||
* @constructor
|
||||
*/
|
||||
public GetHeaders():HttpHeaderData {
|
||||
return this.headers;
|
||||
public GetHeader(name:string):string {
|
||||
return this.headers(name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
/**
|
||||
* @namespace Typertext
|
||||
* @module Http
|
||||
*/
|
||||
module Typertext.Http {
|
||||
/**
|
||||
* @interface HttpHeaderData
|
||||
*/
|
||||
export interface HttpHeaderData {
|
||||
[index:string]:string
|
||||
}
|
||||
}
|
|
@ -7,26 +7,6 @@
|
|||
*/
|
||||
module Typertext.Http {
|
||||
export class HttpRequest implements Typertext.GenericRequest<HttpResponseHandler> {
|
||||
/**
|
||||
* A helper method that takes headers sent by the server and parses it out to an object
|
||||
*
|
||||
* @param {string} headerStr
|
||||
* @returns {HttpHeaderData}
|
||||
*/
|
||||
private static parseHeaderString(headerStr:string):HttpHeaderData {
|
||||
var headers:HttpHeaderData = {},
|
||||
headerPairs:string[] = headerStr.split('\u000d\u000a');
|
||||
for (var i:number = 0; i < headerPairs.length; i++) {
|
||||
var headerPair:string = headerPairs[i],
|
||||
index:number = headerPair.indexOf('\u003a\u0020');
|
||||
if (index > 0) {
|
||||
var key:string = headerPair.substring(0, index);
|
||||
headers[key] = headerPair.substring(index + 2);
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* The class that everything that calls an http(s) server should use and build on top of using callbacks
|
||||
*
|
||||
|
@ -76,9 +56,11 @@ module Typertext.Http {
|
|||
xhr.onreadystatechange = ()=> {
|
||||
//Once the request completes
|
||||
if (xhr.readyState == 4) {
|
||||
var headers:HttpHeaderData = HttpRequest.parseHeaderString(xhr.getAllResponseHeaders());
|
||||
var getHeader = (name:string):string => {
|
||||
return xhr.getResponseHeader(name);
|
||||
};
|
||||
if (xhr.status == 200) {
|
||||
callback(new HttpResponse(HttpResponseStatus.success, headers, xhr.status, xhr.responseText));
|
||||
callback(new HttpResponse(HttpResponseStatus.success, getHeader, xhr.status, xhr.responseText));
|
||||
|
||||
} else if (xhr.status >= 400 && xhr.status < 500) {
|
||||
//TODO generate a client error callback
|
||||
|
|
|
@ -11,7 +11,7 @@ module Typertext.Http {
|
|||
* @extends GenericResponse
|
||||
*
|
||||
* @param {HttpResponseStatus} status
|
||||
* @param {HttpHeaderData} responseHeaders
|
||||
* @param {Function} responseHeaderGetter
|
||||
* @param {number} httpResponseCode
|
||||
* @param {string} responseBody
|
||||
*
|
||||
|
@ -19,8 +19,8 @@ module Typertext.Http {
|
|||
* @version 0.3.0
|
||||
* @constructor
|
||||
*/
|
||||
constructor(status:HttpResponseStatus, responseHeaders?:HttpHeaderData, httpResponseCode?:number, responseBody?:string) {
|
||||
super(status, responseHeaders, httpResponseCode, responseBody);
|
||||
constructor(status:HttpResponseStatus, responseHeaderGetter?:(input:string)=>string, httpResponseCode?:number, responseBody?:string) {
|
||||
super(status, responseHeaderGetter, httpResponseCode, responseBody);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,9 +8,7 @@ module Typertext.Http {
|
|||
private path:string;
|
||||
private port:number;
|
||||
private protocol:HttpProtocol;
|
||||
private queryString:{
|
||||
[index:string]:string
|
||||
};
|
||||
private queryString:HttpQueryString;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -18,7 +16,14 @@ module Typertext.Http {
|
|||
* @returns {number}
|
||||
*/
|
||||
public static DefaultPort(protocol:HttpProtocol) {
|
||||
return ((protocol == HttpProtocol.http) ? 80 : 443)
|
||||
switch(protocol) {
|
||||
case HttpProtocol.http:
|
||||
return 80;
|
||||
case HttpProtocol.https:
|
||||
return 443;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -30,7 +35,7 @@ module Typertext.Http {
|
|||
public static FromUrl(location:string):HttpUrl {
|
||||
var l = document.createElement("a");
|
||||
l.href = location;
|
||||
return new HttpUrl(l.hostname, HttpProtocol[l.protocol], l.pathname, HttpUrl.DecodeQueryString(l.search))
|
||||
return new HttpUrl(l.hostname, HttpProtocol[l.protocol.slice(0,-1)], l.pathname, HttpUrl.DecodeQueryString(l.search), parseInt(l.port))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -40,8 +45,8 @@ module Typertext.Http {
|
|||
* @returns {HttpQueryString}
|
||||
*/
|
||||
public static DecodeQueryString(queryString:string):HttpQueryString {
|
||||
if (queryString.length == 0 || queryString == "?") {
|
||||
return {};
|
||||
if (queryString.indexOf("?") == 0) {
|
||||
queryString = queryString.substring(1);
|
||||
}
|
||||
|
||||
return HttpUrl.UrlDecodeString(queryString);
|
||||
|
@ -84,13 +89,18 @@ module Typertext.Http {
|
|||
public static UrlDecodeString(queryString:string):HttpQueryString {
|
||||
var returnValue:HttpQueryString = {}, params:string[] = HttpUrl.splitString(queryString, "&");
|
||||
for (var i:number = 0; i < params.length; i++) {
|
||||
var param = HttpUrl.splitString(params[i], "=", 2);
|
||||
if (param.length == 1) {
|
||||
returnValue[param[0]] = "";
|
||||
if (params[i] == "") {
|
||||
continue;
|
||||
}
|
||||
|
||||
returnValue[param[0]] = param[1];
|
||||
var param = HttpUrl.splitString(params[i], "=", 2);
|
||||
var key = decodeURIComponent(param[0]);
|
||||
if (param.length == 1) {
|
||||
returnValue[key] = "";
|
||||
continue;
|
||||
}
|
||||
|
||||
returnValue[key] = decodeURIComponent(param[1]);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
|
@ -105,7 +115,7 @@ module Typertext.Http {
|
|||
* @param {number} limit
|
||||
* @returns {string[]}
|
||||
*/
|
||||
private static splitString(input:string, separator:string, limit:number = 0):string[] {
|
||||
private static splitString(input:string, separator:string, limit:number = -1):string[] {
|
||||
limit++;
|
||||
var chunks:string[] = input.split(separator);
|
||||
if (limit > 0 && chunks.length > limit) {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
module Typertext.Json {
|
||||
import HttpResponse = Typertext.Http.HttpResponse;
|
||||
import HttpResponseStatus = Typertext.Http.HttpResponseStatus;
|
||||
import HttpHeaderData = Typertext.Http.HttpHeaderData;
|
||||
|
||||
export class JsonResponse extends Typertext.GenericResponse<JsonObject> {
|
||||
|
||||
|
@ -16,7 +15,7 @@ module Typertext.Json {
|
|||
* @returns {JsonResponse}
|
||||
*/
|
||||
public static fromHttpResponse(httpResponse:HttpResponse):JsonResponse {
|
||||
return new JsonResponse(httpResponse.GetStatus(), httpResponse.GetHeaders(), httpResponse.GetHttpStatus(), window["JSON"].parse(httpResponse.GetContent()));
|
||||
return new JsonResponse(httpResponse.GetStatus(), httpResponse.GetHeader, httpResponse.GetHttpStatus(), window["JSON"].parse(httpResponse.GetContent()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,8 +30,8 @@ module Typertext.Json {
|
|||
* @author Kegan Myers <kegan@keganmyers.com>
|
||||
* @version 0.3.0
|
||||
*/
|
||||
constructor(status:HttpResponseStatus, responseHeaders?:HttpHeaderData, httpResponseCode?:number, responseBody?:JsonObject) {
|
||||
super(status, responseHeaders, httpResponseCode, responseBody);
|
||||
constructor(status:HttpResponseStatus, responseHeaderGetter?:(input:string)=>string, httpResponseCode?:number, responseBody?:JsonObject) {
|
||||
super(status, responseHeaderGetter, httpResponseCode, responseBody);
|
||||
}
|
||||
}
|
||||
}
|
39
package.json
39
package.json
|
@ -1,14 +1,29 @@
|
|||
{
|
||||
"name": "Typertext",
|
||||
"description": "A simple TypeScript HTTP request library",
|
||||
"repository" : {
|
||||
"type" : "git",
|
||||
"url" : "https://github.com/terribleplan/Typertext.git"
|
||||
},
|
||||
"version": "0.3.1",
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.2",
|
||||
"grunt-typescript": "~0.2.7"
|
||||
},
|
||||
"license": "MIT"
|
||||
"name": "Typertext",
|
||||
"description": "A simple TypeScript HTTP request library",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/terribleplan/Typertext.git"
|
||||
},
|
||||
"version": "0.3.1",
|
||||
"devDependencies": {
|
||||
"grunt": "~0.4.2",
|
||||
"grunt-typescript": "~0.2.7",
|
||||
"karma-script-launcher": "~0.1.0",
|
||||
"karma-chrome-launcher": "~0.1.2",
|
||||
"karma-firefox-launcher": "~0.1.3",
|
||||
"karma-html2js-preprocessor": "~0.1.0",
|
||||
"karma-jasmine": "~0.1.5",
|
||||
"karma-coffee-preprocessor": "~0.1.3",
|
||||
"requirejs": "~2.1.11",
|
||||
"karma-requirejs": "~0.2.1",
|
||||
"karma-phantomjs-launcher": "~0.1.2",
|
||||
"karma": "~0.10.9",
|
||||
"grunt-karma": "~0.6.2",
|
||||
"phantomjs": "~1.9.7-1"
|
||||
},
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "./node_modules/.bin/karma start karma.conf.js --single-run"
|
||||
}
|
||||
}
|
||||
|
|
5
test/Typertext/Http/HttpRequest.test.js
Normal file
5
test/Typertext/Http/HttpRequest.test.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
describe("Typertext.Http.HttpRequest", function() {
|
||||
it("Exists", function() {
|
||||
expect(typeof Typertext.Http.HttpRequest).toBe("function");
|
||||
});
|
||||
});
|
256
test/Typertext/Http/HttpUrl.test.js
Normal file
256
test/Typertext/Http/HttpUrl.test.js
Normal file
|
@ -0,0 +1,256 @@
|
|||
describe("Typertext.Http.HttpUrl", function () {
|
||||
it("exists", function () {
|
||||
expect(typeof Typertext.Http.HttpUrl).toBe("function");
|
||||
});
|
||||
|
||||
describe("DefaultPort", function () {
|
||||
it("exists", function () {
|
||||
expect(typeof Typertext.Http.HttpUrl.DefaultPort).toBe("function");
|
||||
});
|
||||
it("returns the correct default port for http", function () {
|
||||
var input = Typertext.Http.HttpProtocol.http,
|
||||
expectedOutput = 80,
|
||||
actualOutput = Typertext.Http.HttpUrl.DefaultPort(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
it("returns the correct default port for https", function () {
|
||||
var input = Typertext.Http.HttpProtocol.https,
|
||||
expectedOutput = 443,
|
||||
actualOutput = Typertext.Http.HttpUrl.DefaultPort(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
it("returns -1 (an invalid port) for any unrecognized protocol", function () {
|
||||
var inputs = [67, "", "nonsense", false, [], function () {
|
||||
}],
|
||||
expectedOutput = -1;
|
||||
|
||||
for (var i = inputs.length - 1; i >= 0; i--) {
|
||||
expect(Typertext.Http.HttpUrl.DefaultPort(inputs[i])).toEqual(expectedOutput);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("FromUrl", function () {
|
||||
it("is a function", function () {
|
||||
expect(typeof Typertext.Http.HttpUrl.FromUrl).toBe("function");
|
||||
});
|
||||
|
||||
it("handles a simple http url", function () {
|
||||
var input = "http://example.com/",
|
||||
expectedOutput = new Typertext.Http.HttpUrl("example.com", Typertext.Http.HttpProtocol.http),
|
||||
actualOutput = Typertext.Http.HttpUrl.FromUrl(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
it("handles a simple https url", function () {
|
||||
var input = "https://example.com/",
|
||||
expectedOutput = new Typertext.Http.HttpUrl("example.com", Typertext.Http.HttpProtocol.https),
|
||||
actualOutput = Typertext.Http.HttpUrl.FromUrl(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
it("handles an http url with a path", function () {
|
||||
var input = "http://example.com/hello",
|
||||
expectedOutput = new Typertext.Http.HttpUrl("example.com", Typertext.Http.HttpProtocol.http, "/hello"),
|
||||
actualOutput = Typertext.Http.HttpUrl.FromUrl(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
it("handles an http url with a path to a file", function () {
|
||||
var input = "http://example.com/index.html",
|
||||
expectedOutput = new Typertext.Http.HttpUrl("example.com", Typertext.Http.HttpProtocol.http, "/index.html"),
|
||||
actualOutput = Typertext.Http.HttpUrl.FromUrl(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
it("handles an http url with a query", function () {
|
||||
var input = "http://example.com/?with=query",
|
||||
expectedOutput = new Typertext.Http.HttpUrl("example.com", Typertext.Http.HttpProtocol.http, "/", {with: "query"}),
|
||||
actualOutput = Typertext.Http.HttpUrl.FromUrl(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
it("handles an http url with a port", function () {
|
||||
var input = "http://example.com:81/",
|
||||
expectedOutput = new Typertext.Http.HttpUrl("example.com", Typertext.Http.HttpProtocol.http, "/", {}, 81),
|
||||
actualOutput = Typertext.Http.HttpUrl.FromUrl(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
it("handles multiple complex urls", function () {
|
||||
var input = "https://example.com:453/path/to/some.php?with=query",
|
||||
expectedOutput = new Typertext.Http.HttpUrl("example.com", Typertext.Http.HttpProtocol.https, "/path/to/some.php", {with: "query"}, 453),
|
||||
actualOutput = Typertext.Http.HttpUrl.FromUrl(input);
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
|
||||
input = "http://example.com:22/path/thing/?without";
|
||||
expectedOutput = new Typertext.Http.HttpUrl("example.com", Typertext.Http.HttpProtocol.http, "/path/thing/", {without: ""}, 22);
|
||||
actualOutput = Typertext.Http.HttpUrl.FromUrl(input);
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
|
||||
input = "https://example.com:80/path/thing/.htaccess?version=125&something=else";
|
||||
expectedOutput = new Typertext.Http.HttpUrl("example.com", Typertext.Http.HttpProtocol.https, "/path/thing/.htaccess", {version: "125", something: "else"}, 80);
|
||||
actualOutput = Typertext.Http.HttpUrl.FromUrl(input);
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
describe("DecodeQueryString", function () {
|
||||
it("follows the same spec as DecodeQueryString, but will remove an optional leading '?'", function () {
|
||||
var input = "?fizz=buzz",
|
||||
expectedOutput = {
|
||||
fizz: "buzz"
|
||||
},
|
||||
actualOutput = Typertext.Http.HttpUrl.DecodeQueryString(input);
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
input = "fizz=buzz";
|
||||
actualOutput = Typertext.Http.HttpUrl.DecodeQueryString(input);
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
|
||||
input = "?foo=bar&fizz=buzz&your=mom";
|
||||
expectedOutput = {
|
||||
fizz: "buzz",
|
||||
foo: "bar",
|
||||
your: "mom"
|
||||
};
|
||||
actualOutput = Typertext.Http.HttpUrl.DecodeQueryString(input);
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
input = "foo=bar&fizz=buzz&your=mom";
|
||||
actualOutput = Typertext.Http.HttpUrl.DecodeQueryString(input);
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
|
||||
input = "?foo=bar&fizz=buzz&enc%26me(=o%40u%23T%24";
|
||||
expectedOutput = {
|
||||
"enc&me(": "o@u#T$",
|
||||
fizz: "buzz",
|
||||
foo: "bar"
|
||||
};
|
||||
actualOutput = Typertext.Http.HttpUrl.DecodeQueryString(input);
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
input = "foo=bar&fizz=buzz&enc%26me(=o%40u%23T%24";
|
||||
actualOutput = Typertext.Http.HttpUrl.DecodeQueryString(input);
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
describe("EncodeQueryString", function () {
|
||||
it("follows the same spec as UrlEncodeObject, but with a prepended '?'", function () {
|
||||
var input = {},
|
||||
expectedOutput = "",
|
||||
actualOutput = Typertext.Http.HttpUrl.EncodeQueryString(input);
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
|
||||
input = {
|
||||
foo: "bar"
|
||||
};
|
||||
expectedOutput = "?foo=bar";
|
||||
actualOutput = Typertext.Http.HttpUrl.EncodeQueryString(input);
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
|
||||
input = {
|
||||
"enc&me(": "o@u#T$"
|
||||
};
|
||||
expectedOutput = "?enc%26me(=o%40u%23T%24";
|
||||
actualOutput = Typertext.Http.HttpUrl.EncodeQueryString(input);
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
|
||||
input = {
|
||||
"foo": "bar",
|
||||
"fizz": "buzz"
|
||||
};
|
||||
expectedOutput = "?foo=bar&fizz=buzz";
|
||||
actualOutput = Typertext.Http.HttpUrl.EncodeQueryString(input);
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
describe("UrlEncodeObject", function () {
|
||||
//TODO
|
||||
it("encodes an empty object as an empty string", function () {
|
||||
var input = {},
|
||||
expectedOutput = "",
|
||||
actualOutput = Typertext.Http.HttpUrl.UrlEncodeObject(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
it("encodes an object with one k/v string pair", function () {
|
||||
var input = {
|
||||
foo: "bar"
|
||||
},
|
||||
expectedOutput = "foo=bar",
|
||||
actualOutput = Typertext.Http.HttpUrl.UrlEncodeObject(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
it("encodes an object with one k/v string pair with special characters in both the key and value", function () {
|
||||
var input = {
|
||||
"enc&me(": "o@u#T$"
|
||||
},
|
||||
expectedOutput = "enc%26me(=o%40u%23T%24",
|
||||
actualOutput = Typertext.Http.HttpUrl.UrlEncodeObject(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
it("encodes multiple key/value pairs", function () {
|
||||
var input = {
|
||||
"foo": "bar",
|
||||
"fizz": "buzz"
|
||||
},
|
||||
expectedOutput = "foo=bar&fizz=buzz",
|
||||
actualOutput = Typertext.Http.HttpUrl.UrlEncodeObject(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
|
||||
describe("UrlDecodeObject", function () {
|
||||
it("decodes an empty string properly", function () {
|
||||
var input = "",
|
||||
expectedOutput = {},
|
||||
actualOutput = Typertext.Http.HttpUrl.UrlDecodeString(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
it("decodes a single key/value pair", function () {
|
||||
var input = "fizz=buzz",
|
||||
expectedOutput = {
|
||||
fizz: "buzz"
|
||||
},
|
||||
actualOutput = Typertext.Http.HttpUrl.UrlDecodeString(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
it("decodes multiple key/value pairs", function () {
|
||||
var input = "foo=bar&fizz=buzz&your=mom",
|
||||
expectedOutput = {
|
||||
fizz: "buzz",
|
||||
foo: "bar",
|
||||
your: "mom"
|
||||
},
|
||||
actualOutput = Typertext.Http.HttpUrl.UrlDecodeString(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
it("decodes key/value pairs with special characters", function () {
|
||||
var input = "foo=bar&fizz=buzz&enc%26me(=o%40u%23T%24",
|
||||
expectedOutput = {
|
||||
"enc&me(": "o@u#T$",
|
||||
fizz: "buzz",
|
||||
foo: "bar"
|
||||
},
|
||||
actualOutput = Typertext.Http.HttpUrl.UrlDecodeString(input);
|
||||
|
||||
expect(actualOutput).toEqual(expectedOutput);
|
||||
});
|
||||
});
|
||||
});
|
Reference in a new issue