Add tests for xhr and friends.
This commit is contained in:
Родитель
40b98c4d7b
Коммит
746ec74663
|
@ -0,0 +1,2 @@
|
||||||
|
Hello,World
|
||||||
|
42,"""fish"""
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1>Hello & world!</h1>
|
||||||
|
</html>
|
|
@ -0,0 +1 @@
|
||||||
|
[{"Hello":42,"World":"\"fish\""}]
|
|
@ -0,0 +1 @@
|
||||||
|
Hello, world!
|
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<hello>
|
||||||
|
<world name="Earth"/>
|
||||||
|
</hello>
|
|
@ -0,0 +1,37 @@
|
||||||
|
require("../env");
|
||||||
|
require("../../d3");
|
||||||
|
|
||||||
|
var vows = require("vows"),
|
||||||
|
assert = require("assert");
|
||||||
|
|
||||||
|
var suite = vows.describe("d3.html");
|
||||||
|
|
||||||
|
suite.addBatch({
|
||||||
|
"html": {
|
||||||
|
topic: function() {
|
||||||
|
var cb = this.callback;
|
||||||
|
return d3.html("examples/data/sample.html", function(document) {
|
||||||
|
cb(null, document);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"invokes the callback with the loaded html": function(document) {
|
||||||
|
assert.equal(document.getElementsByTagName("H1")[0].textContent, "Hello & world!");
|
||||||
|
},
|
||||||
|
"override the mime type to text/html": function(xml) {
|
||||||
|
assert.equal(XMLHttpRequest._last._info.mimeType, "text/html");
|
||||||
|
},
|
||||||
|
"": {
|
||||||
|
topic: function() {
|
||||||
|
var cb = this.callback;
|
||||||
|
return d3.html("//does/not/exist.html", function(document) {
|
||||||
|
cb(null, document);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"invokes the callback with null when an error occurs": function(document) {
|
||||||
|
assert.isNull(document);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
suite.export(module);
|
|
@ -0,0 +1,37 @@
|
||||||
|
require("../env");
|
||||||
|
require("../../d3");
|
||||||
|
|
||||||
|
var vows = require("vows"),
|
||||||
|
assert = require("assert");
|
||||||
|
|
||||||
|
var suite = vows.describe("d3.json");
|
||||||
|
|
||||||
|
suite.addBatch({
|
||||||
|
"json": {
|
||||||
|
topic: function() {
|
||||||
|
var cb = this.callback;
|
||||||
|
return d3.json("examples/data/sample.json", function(json) {
|
||||||
|
cb(null, json);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"invokes the callback with the loaded JSON": function(json) {
|
||||||
|
assert.deepEqual(json, [{"Hello":42,"World":"\"fish\""}]);
|
||||||
|
},
|
||||||
|
"overrides the mime type to application/json": function(json) {
|
||||||
|
assert.equal(XMLHttpRequest._last._info.mimeType, "application/json");
|
||||||
|
},
|
||||||
|
"": {
|
||||||
|
topic: function() {
|
||||||
|
var cb = this.callback;
|
||||||
|
return d3.json("//does/not/exist.json", function(json) {
|
||||||
|
cb(null, json);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"invokes the callback with null when an error occurs": function(json) {
|
||||||
|
assert.isNull(json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
suite.export(module);
|
|
@ -0,0 +1,48 @@
|
||||||
|
require("../env");
|
||||||
|
require("../../d3");
|
||||||
|
|
||||||
|
var vows = require("vows"),
|
||||||
|
assert = require("assert");
|
||||||
|
|
||||||
|
var suite = vows.describe("d3.text");
|
||||||
|
|
||||||
|
suite.addBatch({
|
||||||
|
"text": {
|
||||||
|
topic: function() {
|
||||||
|
var cb = this.callback;
|
||||||
|
return d3.text("examples/data/sample.txt", function(text) {
|
||||||
|
cb(null, text);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"invokes the callback with the loaded text": function(text) {
|
||||||
|
assert.equal(text, "Hello, world!\n");
|
||||||
|
},
|
||||||
|
"does not override the mime type by default": function(text) {
|
||||||
|
assert.isUndefined(XMLHttpRequest._last._info.mimeType);
|
||||||
|
},
|
||||||
|
"": {
|
||||||
|
topic: function() {
|
||||||
|
var cb = this.callback;
|
||||||
|
return d3.text("examples/data/sample.txt", "text/plain+sample", function(text) {
|
||||||
|
cb(null, text);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"observes the optional mime type": function(text) {
|
||||||
|
assert.equal(XMLHttpRequest._last._info.mimeType, "text/plain+sample");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
" ": {
|
||||||
|
topic: function() {
|
||||||
|
var cb = this.callback;
|
||||||
|
return d3.text("//does/not/exist.txt", function(text) {
|
||||||
|
cb(null, text);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"invokes the callback with null when an error occurs": function(text) {
|
||||||
|
assert.isNull(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
suite.export(module);
|
|
@ -0,0 +1,56 @@
|
||||||
|
require("../env");
|
||||||
|
require("../../d3");
|
||||||
|
|
||||||
|
var vows = require("vows"),
|
||||||
|
assert = require("assert");
|
||||||
|
|
||||||
|
var suite = vows.describe("d3.xhr");
|
||||||
|
|
||||||
|
suite.addBatch({
|
||||||
|
"xhr": {
|
||||||
|
topic: function() {
|
||||||
|
var cb = this.callback;
|
||||||
|
return d3.xhr("examples/data/sample.txt", function(req) {
|
||||||
|
cb(null, req);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"makes an asynchronous HTTP request": function(req) {
|
||||||
|
assert.equal(req._info.url, "examples/data/sample.txt");
|
||||||
|
assert.isTrue(req._info.async);
|
||||||
|
},
|
||||||
|
"invokes the callback with the request object": function(req) {
|
||||||
|
assert.equal(req.responseText, "Hello, world!\n");
|
||||||
|
},
|
||||||
|
"does not override the mime type by default": function(req) {
|
||||||
|
assert.isUndefined(req._info.mimeType);
|
||||||
|
},
|
||||||
|
"waits until the request is done": function(req) {
|
||||||
|
assert.equal(req.readyState, 4);
|
||||||
|
assert.equal(req.status, 200);
|
||||||
|
},
|
||||||
|
"": {
|
||||||
|
topic: function() {
|
||||||
|
var cb = this.callback;
|
||||||
|
return d3.xhr("examples/data/sample.txt", "text/plain", function(req) {
|
||||||
|
cb(null, req);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"observes the optional mime type": function(req) {
|
||||||
|
assert.equal(req._info.mimeType, "text/plain");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
" ": {
|
||||||
|
topic: function() {
|
||||||
|
var cb = this.callback;
|
||||||
|
return d3.xhr("//does/not/exist.txt", function(req) {
|
||||||
|
cb(null, req);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"invokes the callback with null when an error occurs": function(req) {
|
||||||
|
assert.isNull(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
suite.export(module);
|
|
@ -0,0 +1,48 @@
|
||||||
|
require("../env");
|
||||||
|
require("../../d3");
|
||||||
|
|
||||||
|
var vows = require("vows"),
|
||||||
|
assert = require("assert");
|
||||||
|
|
||||||
|
var suite = vows.describe("d3.xml");
|
||||||
|
|
||||||
|
suite.addBatch({
|
||||||
|
"xml": {
|
||||||
|
topic: function() {
|
||||||
|
var cb = this.callback;
|
||||||
|
return d3.xml("examples/data/sample.xml", function(xml) {
|
||||||
|
cb(null, xml);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"invokes the callback with the loaded xml": function(xml) {
|
||||||
|
assert.deepEqual(xml, {_xml: "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<hello>\n <world name=\"Earth\"/>\n</hello>\n"});
|
||||||
|
},
|
||||||
|
"does not override the mime type by default": function(xml) {
|
||||||
|
assert.isUndefined(XMLHttpRequest._last._info.mimeType);
|
||||||
|
},
|
||||||
|
"": {
|
||||||
|
topic: function() {
|
||||||
|
var cb = this.callback;
|
||||||
|
return d3.xml("examples/data/sample.txt", "application/xml+sample", function(xml) {
|
||||||
|
cb(null, xml);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"observes the optional mime type": function(xml) {
|
||||||
|
assert.equal(XMLHttpRequest._last._info.mimeType, "application/xml+sample");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
" ": {
|
||||||
|
topic: function() {
|
||||||
|
var cb = this.callback;
|
||||||
|
return d3.xml("//does/not/exist.xml", function(xml) {
|
||||||
|
cb(null, xml);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
"invokes the callback with null when an error occurs": function(xml) {
|
||||||
|
assert.isNull(xml);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
suite.export(module);
|
|
@ -0,0 +1,72 @@
|
||||||
|
var assert = require("assert");
|
||||||
|
|
||||||
|
assert.inDelta = function (actual, expected, delta, message) {
|
||||||
|
var lower = expected - delta;
|
||||||
|
var upper = expected + delta;
|
||||||
|
if (actual != +actual || actual < lower || actual > upper) {
|
||||||
|
assert.fail(actual, expected, message || "expected {actual} to be in within *" + delta.toString() + "* of {expected}", null, assert.inDelta);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.domNull = function(actual, message) {
|
||||||
|
if (actual !== null) {
|
||||||
|
assert.fail(actual+"", null, message || "expected null, got {actual}", "===", assert.domNull);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.domEqual = function(actual, expected, message) {
|
||||||
|
if (actual !== expected) {
|
||||||
|
assert.fail(actual+"", expected+"", message || "expected {expected}, got {actual}", "===", assert.domEqual);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.rgbEqual = function(actual, r, g, b, message) {
|
||||||
|
if (actual.r !== r || actual.g !== g || actual.b !== b) {
|
||||||
|
assert.fail("rgb(" + actual.r + "," + actual.g + "," + actual.b + ")", "rgb(" + r + ", " + g + ", " + b + ")", message || "expected {expected}, got {actual}", "===", assert.rgbEqual);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.hslEqual = function(actual, h, s, l, message) {
|
||||||
|
if (Math.abs(actual.h - h) > 1e-6 || Math.abs(actual.s - s) > 1e-6 || Math.abs(actual.l - l) > 1e-6) {
|
||||||
|
assert.fail(actual+"", "hsl(" + h + "," + (s * 100) + "%," + (l * 100) + "%)", message || "expected {expected}, got {actual}", null, assert.hslEqual);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
assert.pathEqual = function(actual, expected, message) {
|
||||||
|
if (!pathEqual(actual, expected)) {
|
||||||
|
assert.fail(actual, expected, message || "expected {expected}, got {actual}", null, assert.pathEqual);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function pathEqual(a, b) {
|
||||||
|
a = parsePath(a);
|
||||||
|
b = parsePath(b);
|
||||||
|
var n = a.length, i = -1, x, y;
|
||||||
|
if (n !== b.length) return false;
|
||||||
|
while (++i < n) {
|
||||||
|
x = a[i];
|
||||||
|
y = b[i];
|
||||||
|
if (typeof x === "string") {
|
||||||
|
if (x !== y) return false;
|
||||||
|
} else if (typeof y !== "number") {
|
||||||
|
return false;
|
||||||
|
} else if (Math.abs(x - y) > 1e-6) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parsePath(path) {
|
||||||
|
var re = /[-+]?(?:\d+\.\d+|\d+\.|\.\d+|\d+)(?:[eE][-]?\d+)?/g, parts = [];
|
||||||
|
for (var i = 0, s0 = 0, s1, m; m = re.exec(path); ++i) {
|
||||||
|
if (m.index) {
|
||||||
|
var part = path.substring(s0, s1 = m.index);
|
||||||
|
if (!/^[, ]$/.test(part)) parts.push(part);
|
||||||
|
}
|
||||||
|
parts.push(parseFloat(m[0]));
|
||||||
|
s0 = re.lastIndex;
|
||||||
|
}
|
||||||
|
if (s0 < path.length) parts.push(path.substring(s0));
|
||||||
|
return parts;
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
var jsdom = require("jsdom");
|
||||||
|
|
||||||
|
document.createRange = function() {
|
||||||
|
return {
|
||||||
|
selectNode: function() {},
|
||||||
|
createContextualFragment: function(html) { return jsdom.jsdom(html); }
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,56 @@
|
||||||
|
var fs = require("fs");
|
||||||
|
|
||||||
|
XMLHttpRequest = function() {
|
||||||
|
var self = this,
|
||||||
|
info = self._info = {},
|
||||||
|
headers = {},
|
||||||
|
url;
|
||||||
|
|
||||||
|
// TODO handle file system errors?
|
||||||
|
|
||||||
|
self.open = function(m, u, a) {
|
||||||
|
info.url = u;
|
||||||
|
info.async = a;
|
||||||
|
Object.freeze(info);
|
||||||
|
self.send = a ? read : readSync;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.overrideMimeType = function(x) {
|
||||||
|
info.mimeType = x;
|
||||||
|
};
|
||||||
|
|
||||||
|
function read() {
|
||||||
|
fs.readFile(info.url, "binary", function(e, d) {
|
||||||
|
if (e) {
|
||||||
|
self.status = 404; // assumed
|
||||||
|
} else {
|
||||||
|
self.status = 200;
|
||||||
|
self.responseText = d;
|
||||||
|
self.responseXML = {_xml: d};
|
||||||
|
headers["Content-Length"] = d.length;
|
||||||
|
}
|
||||||
|
self.readyState = 4;
|
||||||
|
XMLHttpRequest._last = self;
|
||||||
|
if (self.onreadystatechange) self.onreadystatechange();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function readSync() {
|
||||||
|
try {
|
||||||
|
var d = fs.readFileSync(info.url, "binary");
|
||||||
|
self.status = 200;
|
||||||
|
self.responseText = d;
|
||||||
|
self.responseXML = {_xml: d};
|
||||||
|
headers["Content-Length"] = d.length;
|
||||||
|
} catch (e) {
|
||||||
|
self.status = 404; // assumed
|
||||||
|
}
|
||||||
|
self.readyState = 4;
|
||||||
|
XMLHttpRequest._last = self;
|
||||||
|
if (self.onreadystatechange) self.onreadystatechange();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.getResponseHeader = function(n) {
|
||||||
|
return headers[n];
|
||||||
|
};
|
||||||
|
};
|
75
test/env.js
75
test/env.js
|
@ -7,75 +7,6 @@ Sizzle = window.Sizzle;
|
||||||
|
|
||||||
process.env.TZ = "America/Los_Angeles";
|
process.env.TZ = "America/Los_Angeles";
|
||||||
|
|
||||||
var assert = require("assert");
|
require("./env-assert");
|
||||||
|
require("./env-xhr");
|
||||||
assert.inDelta = function (actual, expected, delta, message) {
|
require("./env-fragment");
|
||||||
var lower = expected - delta;
|
|
||||||
var upper = expected + delta;
|
|
||||||
if (actual != +actual || actual < lower || actual > upper) {
|
|
||||||
assert.fail(actual, expected, message || "expected {actual} to be in within *" + delta.toString() + "* of {expected}", null, assert.inDelta);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.domNull = function(actual, message) {
|
|
||||||
if (actual !== null) {
|
|
||||||
assert.fail(actual+"", null, message || "expected null, got {actual}", "===", assert.domNull);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.domEqual = function(actual, expected, message) {
|
|
||||||
if (actual !== expected) {
|
|
||||||
assert.fail(actual+"", expected+"", message || "expected {expected}, got {actual}", "===", assert.domEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.rgbEqual = function(actual, r, g, b, message) {
|
|
||||||
if (actual.r !== r || actual.g !== g || actual.b !== b) {
|
|
||||||
assert.fail("rgb(" + actual.r + "," + actual.g + "," + actual.b + ")", "rgb(" + r + ", " + g + ", " + b + ")", message || "expected {expected}, got {actual}", "===", assert.rgbEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.hslEqual = function(actual, h, s, l, message) {
|
|
||||||
if (Math.abs(actual.h - h) > 1e-6 || Math.abs(actual.s - s) > 1e-6 || Math.abs(actual.l - l) > 1e-6) {
|
|
||||||
assert.fail(actual+"", "hsl(" + h + "," + (s * 100) + "%," + (l * 100) + "%)", message || "expected {expected}, got {actual}", null, assert.hslEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
assert.pathEqual = function(actual, expected, message) {
|
|
||||||
if (!pathEqual(actual, expected)) {
|
|
||||||
assert.fail(actual, expected, message || "expected {expected}, got {actual}", null, assert.pathEqual);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function pathEqual(a, b) {
|
|
||||||
a = parsePath(a);
|
|
||||||
b = parsePath(b);
|
|
||||||
var n = a.length, i = -1, x, y;
|
|
||||||
if (n !== b.length) return false;
|
|
||||||
while (++i < n) {
|
|
||||||
x = a[i];
|
|
||||||
y = b[i];
|
|
||||||
if (typeof x === "string") {
|
|
||||||
if (x !== y) return false;
|
|
||||||
} else if (typeof y !== "number") {
|
|
||||||
return false;
|
|
||||||
} else if (Math.abs(x - y) > 1e-6) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parsePath(path) {
|
|
||||||
var re = /[-+]?(?:\d+\.\d+|\d+\.|\.\d+|\d+)(?:[eE][-]?\d+)?/g, parts = [];
|
|
||||||
for (var i = 0, s0 = 0, s1, m; m = re.exec(path); ++i) {
|
|
||||||
if (m.index) {
|
|
||||||
var part = path.substring(s0, s1 = m.index);
|
|
||||||
if (!/^[, ]$/.test(part)) parts.push(part);
|
|
||||||
}
|
|
||||||
parts.push(parseFloat(m[0]));
|
|
||||||
s0 = re.lastIndex;
|
|
||||||
}
|
|
||||||
if (s0 < path.length) parts.push(path.substring(s0));
|
|
||||||
return parts;
|
|
||||||
}
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче