Comparing version 0.4.0 to 0.4.1
@@ -163,2 +163,4 @@ var foldHeaderLine = require('./foldHeaderLine'), | ||
return !!values; | ||
} else if (typeof values === 'undefined') { | ||
return false; | ||
} else { | ||
@@ -210,2 +212,42 @@ if (Array.isArray(stringOrArray)) { | ||
// Exploratory work wrt. https://github.com/sunesimonsen/unexpected/issues/40 | ||
Headers.prototype.satisfy = function (spec, mustBeExhaustive) { | ||
if (spec && typeof spec === 'object' && !(spec instanceof Headers)) { | ||
// A value of 'undefined' means that the header must be absent: | ||
if (Object.keys(spec).some(function (headerName) { | ||
return typeof spec[headerName] === 'undefined' && this.has(headerName); | ||
}, this)) { | ||
return false; | ||
} | ||
} | ||
var expectedHeaders = spec instanceof Headers ? spec : new Headers(spec), | ||
expectedHeaderNames = expectedHeaders.getNames(); | ||
if (mustBeExhaustive && expectedHeaderNames.length < this.getNames().length) { | ||
return false; | ||
} | ||
return expectedHeaderNames.every(function (expectedHeaderName) { | ||
var expectedValues = expectedHeaders.getAll(expectedHeaderName); | ||
if (mustBeExhaustive) { | ||
var values = this.getAll(expectedHeaderName); | ||
if (expectedValues.length !== values.length) { | ||
return false; | ||
} | ||
if (values.length > 1 || expectedValues.length > 1) { | ||
values.sort(); | ||
expectedValues.sort(); | ||
if (!values.every(function (value, i) { | ||
return value === expectedValues[i]; | ||
})) { | ||
return false; | ||
} | ||
} | ||
} | ||
return this.has(expectedHeaderName, expectedValues); | ||
}, this); | ||
}; | ||
Headers.prototype.toString = function (maxLineLength) { | ||
@@ -212,0 +254,0 @@ var result = '', |
@@ -56,2 +56,79 @@ /*global unescape*/ | ||
function buffersEqual(a, b) { | ||
if (a === b) { | ||
return true; | ||
} | ||
if (a.length !== b.length) return false; | ||
for (var i = 0; i < a.length; i += 1) { | ||
if (a[i] !== b[i]) return false; | ||
} | ||
return true; | ||
} | ||
function isNonBufferObject(obj) { | ||
return obj && typeof obj === 'object' && !Buffer.isBuffer(obj); | ||
} | ||
function canonicalizeObject(obj, stack) { | ||
stack = stack || []; | ||
if (stack.indexOf(obj) !== -1) return '[Circular]'; | ||
var canonicalizedObject; | ||
if ({}.toString.call(obj) === '[object Array]') { | ||
stack.push(obj); | ||
canonicalizedObject = exports.map(obj, function (item) { | ||
return canonicalizeObject(item, stack); | ||
}); | ||
stack.pop(); | ||
} else if (typeof obj === 'object' && obj !== null) { | ||
stack.push(obj); | ||
canonicalizedObject = {}; | ||
Object.keys(obj).sort().forEach(function (key) { | ||
canonicalizedObject[key] = canonicalizeObject(obj[key], stack); | ||
}); | ||
stack.pop(); | ||
} else { | ||
canonicalizedObject = obj; | ||
} | ||
return canonicalizedObject; | ||
} | ||
// Exploratory work wrt. https://github.com/sunesimonsen/unexpected/issues/40 | ||
Message.prototype.satisfies = function (spec, mustBeExhaustive) { | ||
if (typeof spec === 'string') { | ||
spec = new Message(spec); | ||
} | ||
if ('headers' in spec && !this.headers.satisfy(spec.headers)) { | ||
return false; | ||
} | ||
if ('body' in spec) { | ||
if (Buffer.isBuffer(spec.body) && Buffer.isBuffer(this.body)) { | ||
if (!buffersEqual(spec.body, this.body)) { | ||
return false; | ||
} | ||
} else if (typeof spec.body === 'string' && typeof this.body === 'string') { | ||
if (spec.body !== this.body) { | ||
return false; | ||
} | ||
} else if (isNonBufferObject(spec.body) && isNonBufferObject(this.body)) { | ||
if (JSON.stringify(canonicalizeObject(spec.body)) !== JSON.stringify(canonicalizeObject(this.body))) { | ||
return false; | ||
} | ||
} else { | ||
throw new Error('Unsupported comparison between different types of bodies'); | ||
} | ||
if (typeof this.body === 'undefined') { | ||
} | ||
} | ||
return true; | ||
}; | ||
Message.prototype.toString = function (maxLineLength) { | ||
@@ -58,0 +135,0 @@ if (typeof maxLineLength === 'undefined') { |
{ | ||
"name": "messy", | ||
"version": "0.4.0", | ||
"version": "0.4.1", | ||
"description": "Object model for HTTP and RFC822 messages", | ||
@@ -5,0 +5,0 @@ "main": "lib/index.js", |
@@ -28,2 +28,75 @@ /*global describe, it*/ | ||
}); | ||
}); | ||
describe('#satisfy', function () { | ||
it('must match an empty object', function () { | ||
expect(new Headers({foo: 'a'}).satisfy({}), 'to be true'); | ||
}); | ||
it('must match an empty object exhaustively', function () { | ||
expect(new Headers({}).satisfy({}, true), 'to be true'); | ||
}); | ||
it('must match a single-valued header', function () { | ||
expect(new Headers({foo: 'a'}).satisfy({foo: 'a'}), 'to be true'); | ||
}); | ||
it('must match a single-valued header specified with a different casing', function () { | ||
expect(new Headers({Foo: 'a'}).satisfy({fOO: 'a'}), 'to be true'); | ||
}); | ||
it('must match exhaustively when a single header is matched', function () { | ||
expect(new Headers({foo: 'a'}).satisfy({foo: 'a'}, true), 'to be true'); | ||
}); | ||
it('must match a different value type (should stringify everything)', function () { | ||
expect(new Headers({foo: '123'}).satisfy({foo: 123}), 'to be true'); | ||
expect(new Headers({foo: 123}).satisfy({foo: '123'}), 'to be true'); | ||
}); | ||
it('should match in spite of excess headers when not matching exhaustively', function () { | ||
expect(new Headers({foo: 'a', bar: 'a'}).satisfy({foo: 'a'}), 'to be true'); | ||
}); | ||
it('should not match exhaustively when there are excess headers', function () { | ||
expect(new Headers({foo: 'a', bar: 'a'}).satisfy({foo: 'a'}, true), 'to be false'); | ||
}); | ||
it('should match in spite of excess values when not matching exhaustively', function () { | ||
expect(new Headers({foo: ['a', 'b']}).satisfy({foo: 'a'}), 'to be true'); | ||
}); | ||
it('should not match exhaustively when there are excess values', function () { | ||
expect(new Headers({foo: ['a', 'b']}).satisfy({foo: 'a'}, true), 'to be false'); | ||
}); | ||
it('should match multiple values exhaustively', function () { | ||
expect(new Headers({foo: ['a', 'b']}).satisfy({foo: ['a', 'b']}, true), 'to be true'); | ||
}); | ||
it('should match multiple values exhaustively when ordered differently', function () { | ||
expect(new Headers({foo: ['a', 'b']}).satisfy({foo: ['b', 'a']}, true), 'to be true'); | ||
}); | ||
it('should not match exhaustively unless all values are actually named', function () { | ||
expect(new Headers({foo: ['a', 'b']}).satisfy({foo: ['a', 'a']}, true), 'to be false'); | ||
}); | ||
it('should assert the absence of a header when the value is given as undefined', function () { | ||
expect(new Headers({foo: 'a'}).satisfy({bar: undefined}), 'to be true'); | ||
expect(new Headers({foo: 'a'}).satisfy({foo: undefined}), 'to be false'); | ||
}); | ||
it('should match exhaustively even when absent headers are also asserted absent', function () { | ||
expect(new Headers({foo: 'a'}).satisfy({foo: 'a', bar: undefined}, true), 'to be true'); | ||
}); | ||
it('should support passing the expected set of headers as a string', function () { | ||
expect(new Headers({foo: 'a', bar: 'b'}).satisfy('foo: a\r\nbar: b'), 'to be true'); | ||
expect(new Headers({foo: 'a', bar: 'b'}).satisfy('foo: a\r\nbar: b', true), 'to be true'); | ||
expect(new Headers({foo: 'a'}).satisfy('foo: b'), 'to be false'); | ||
expect(new Headers({foo: 'a'}).satisfy(''), 'to be true'); | ||
expect(new Headers({foo: 'a'}).satisfy('', true), 'to be false'); | ||
}); | ||
}); | ||
}); |
@@ -174,2 +174,36 @@ /*global describe, it*/ | ||
}); | ||
describe('#satisfies', function () { | ||
it('should support matching the headers', function () { | ||
expect(new Message({headers: {foo: 'a'}}).satisfies({headers: {foo: 'a'}}), 'to be true'); | ||
}); | ||
it('should support matching the headers', function () { | ||
expect(new Message({headers: {foo: 'a'}}).satisfies({headers: {foo: 'a'}}), 'to be true'); | ||
expect(new Message({headers: {foo: 'a'}}).satisfies({headers: {bar: 'a'}}), 'to be false'); | ||
}); | ||
it('should support passing the expected properties as a string', function () { | ||
expect(new Message({headers: {foo: 'a'}}).satisfies('foo: a'), 'to be true'); | ||
expect(new Message({headers: {foo: 'a'}}).satisfies('foo: b'), 'to be false'); | ||
}); | ||
it('should support passing the expected headers as a string', function () { | ||
expect(new Message({headers: {foo: 'a'}}).satisfies({headers: 'foo: a'}), 'to be true'); | ||
expect(new Message({headers: {foo: 'a'}}).satisfies({headers: 'foo: b'}), 'to be false'); | ||
}); | ||
it('should support matching a string body with a string', function () { | ||
expect(new Message('foo: bar\n\nthe body').satisfies({body: 'the body'}), 'to be true'); | ||
}); | ||
it('should support matching a Buffer body with a Buffer', function () { | ||
expect(new Message(new Buffer('foo: bar\n\nthe body', 'utf-8')).satisfies({body: new Buffer('the body', 'utf-8')}), 'to be true'); | ||
}); | ||
it('should support matching a object body (JSON) with an object', function () { | ||
expect(new Message({body: {foo: 'bar', bar: 'baz'}}).satisfies({body: {bar: 'baz', foo: 'bar'}}), 'to be true'); | ||
}); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
53066
1029