vows-is.js | |
---|---|
var fluent = require("vows-fluent"),
request = require("request"),
Assertion = require("should").Assertion.prototype,
Trait = require("traits").Trait,
Topic = fluent.Topic,
Vow = fluent.Vow,
Context = fluent.Context; | |
Remove should from the prototype. | delete Object.prototype.should; |
defaults objects overwritten through config. | var defaults = {}, |
test whether an url is an url or has a method in it. | test_uri = /^(GET|POST|PUT|HEAD|DELETE)(.*)/; |
utility create function | var create = function _create(trait) {
return Object.create(Object.prototype, trait)
}; |
Is object used in topic().is | exports.Is = { |
dummy getter | get a() {
return this;
}, |
request. This sets the value of the topic to be a request function.
It goes off and asks for a server from the server factory,
Then generates the url to request. It makes a request to your
server then uses | "request": function _request(url) {
this._parent.set(function _topic() {
var cb = this.callback;
defaults.server.factory(function _getServer(server) {
var options = {};
var match = url && url.match(test_uri);
if (match) {
options.method = match[1];
options.uri = defaults.server.uri + match[2].substr(1);
} else {
options.uri = defaults.server.uri + uri
}
request(options, function _handleRequest(err, res, body) {
server.close();
cb(err, res);
});
});
});
return this.end()
}, |
Set the topic to be a property of the current topic | "property": function _property(name) {
this._parent.set(function _topic(topic) {
return topic[name];
});
return this.end()
}, |
end the is abstraction returning the context owning the topic. | "end": function _end() {
return this._parent.parent()
}
}; |
Property descriptor for property is.
Creates a Is, sets the parent and returns it.
Typeof function check supports | var propertyDescriptorIs = {
"set": function _set() {},
"get": function _get() {
var i = create(Trait(exports.Is));
if (typeof this === "function") {
i._parent = this();
} else {
i._parent = this;
}
var f = (function _is(val) {
this._parent.set(val);
return this.end();
}).bind(i);
var keys = Object.getOwnPropertyNames(i);
keys.forEach(function(key) {
var pd = Object.getOwnPropertyDescriptor(i, key);
Object.defineProperty(f, key, pd);
});
return f;
}
}; |
Add is as a getter to the topic to support | Object.defineProperty(Topic, "is", propertyDescriptorIs); |
replace topic method with a getter that returns the function
make sure to bind this and add the | var old_topic = Context.topic;
Object.defineProperty(Context, "topic", {
"set": function _set() {},
"get": function _get() {
var f = old_topic.bind(this);
Object.defineProperty(f, "is", propertyDescriptorIs);
return f;
}
}); |
It object used in | exports.It = { |
Creates a should wrapper and returns it. Also sets the vow value to unwrap the should wrapper. | get should() {
var s = create(Trait(exports.Should));
s._stack = [];
s._parent = this._parent;
return s;
}
} |
Property descriptor for property it.
Creates a It, sets the parent and returns it.
Typeof function check supports | var propertyDescriptorIt = {
"set": function _set() {},
"get": function _get() {
var i = create(Trait(exports.It));
if (typeof this === "function") {
i._parent = this();
} else {
i._parent = this;
}
return i;
}
}; |
Add is as a getter on Vow to support | Object.defineProperty(Vow, "it", propertyDescriptorIt); |
Replace vow method with a getter that returns the function
make sure to bind the scope and add | var old_vow = Context.vow
Object.defineProperty(Context, "vow", {
"set": function _set() {},
"get": function _get() {
var f = old_vow.bind(this);
Object.defineProperty(f, "it", propertyDescriptorIt);
return f;
}
}); |
Extension of the should.js Assertion object | exports.Assertion = create(Trait.override(Trait({ |
header. Assert it has property headers and that the
header | "header": function _header(name, val) {
return this.property("headers").with.property(name, val);
}
}), Trait(Assertion))); |
a Should object which is a wrapper around should.js | exports.Should = { |
error getter. Set's the object to the error and calls ok. | get error() {
s._obj = s._error
return this.ok();
}, |
transforms the stack into a nice assertion string | "prettyPrint": function _prettyPrint() {
var arr = this._stack.map(function _map(val) {
var str = val.key;
if (exports.prettyPrint[val.key]) {
str += " " + exports.prettyPrint[val.key](val.args);
} else if (val.args.length) {
str += " " + val.args.join(" ");
}
return str;
});
arr.unshift("should");
return arr.join(" ");
}, |
end the abstraction. This creates a should.js assertion and unravels the stack running every assertion. it then returns context that the vow belongs to. | "end": function _end() {
var s = create(Trait(exports.Assertion));
s.obj = this._obj;
this._stack.forEach(function _each(val) {
if (val.type === 'get') {
s = s[val.key];
} else {
s = s[val.key].apply(s, val.args);
}
});
return this._parent.parent();
}
}; |
A stack of prettyPrint methods to make the assertions look pretty | exports.prettyPrint = {
"header": function _property(args) {
return args[0] + " with value " + args[1];
}
}; |
For each of the methods that can be called on a context add them to should. This tells the Should wrappers to end itself and return back to the context. | ["vow", "context", "parent", "batch", "suite"].forEach(function _each(key) {
exports.Should[key] = function _parent() {
var parent = this._parent.parent();
if (!this._parent._name) {
this._parent.name(this.prettyPrint());
}
var that = this;
this._parent.set(function _set(err, value) {
that._obj = value;
that._error = err;
that.end();
});
return parent[key].apply(parent, arguments);
};
}); |
Replace the vow method of Should with a getter so chaining doesn't break | var should_vow = exports.Should.vow
Object.defineProperty(exports.Should, "vow", {
"set": function _set() {},
"get": function _get() {
var f = should_vow.bind(this);
Object.defineProperty(f, "it", propertyDescriptorIt);
return f;
}
}); |
For each of the methods of | Object.keys(exports.Assertion).forEach(function _each(key) {
if (!exports.Should.hasOwnProperty(key)) {
var descriptor = Object.getOwnPropertyDescriptor(exports.Assertion, key);
var name = descriptor.get ? "get" : "value";
descriptor[name] = function _descriptor() {
this._stack.push({
"type": name,
"key": key,
"args": Array.prototype.slice.call(arguments)
});
return this;
}
Object.defineProperty(exports.Should, key, descriptor);
}
}); |
Config method sets defaults | exports.config = function _init(obj) {
Object.keys(obj).forEach(function _each(key) {
defaults[key] = obj[key];
});
}; |
Expose methods of vows-fluent on exports. | Object.keys(fluent).forEach(function _each(key) {
exports[key] = fluent[key];
});
|