betwixt
Version:
String rank for re-orderable lists
273 lines (267 loc) • 10.8 kB
JavaScript
(function() {
var Betwixt, path;
path = require("path");
Betwixt = require(path.join("..", "betwixt"));
require("jasmine-given");
describe("Betwixt", function() {
var zero;
Given(function() {
return this.Betwixt = Betwixt;
});
Given(function() {
return this.zero = "\u0000";
});
zero = "\u0000";
describe("trim", function() {
return it("should trim trailing zeros", function() {
expect(Betwixt.trim("\uaaaa\u0000")).toEqual("\uaaaa");
return expect(Betwixt.trim("\u0000")).toEqual("");
});
});
describe("validated", function() {
var nonempty;
nonempty = "\uaaaa\u0000";
it("should return the same value as trim for nonempty strings", function() {
return expect(Betwixt.validated(nonempty)).toEqual(Betwixt.trim(nonempty));
});
return it("should throw an error if its parameter is zero/empty", function() {
expect(function() {
return Betwixt.validated(zero);
}).toThrowError(Error);
return expect(function() {
return Betwixt.validated("");
}).toThrowError(Error);
});
});
describe("midpoint", function() {
Given(function() {
return this.m = this.Betwixt.midpoint();
});
return Then(function() {
return this.m === "\u8000";
});
});
describe("toHex", function() {
return Then(function() {
return this.Betwixt.toHex("\uBEAD\ucafe") === "beadcafe";
});
});
describe("before and after", function() {
Given(function() {
return this.start = "\u1234";
});
Given(function() {
return this.extra = "\ufade\ucafe";
});
Given(function() {
return this.ffff = "\uffff";
});
describe("They trim their arguments", function() {
Then(function() {
return this.Betwixt.before(this.start + this.zero) === this.Betwixt.before(this.start);
});
Then(function() {
return this.Betwixt.before(this.ffff + this.zero) === this.Betwixt.before(this.ffff);
});
Then(function() {
return this.Betwixt.after(this.ffff + this.zero) === this.Betwixt.after(this.ffff);
});
return Then(function() {
return this.Betwixt.after(this.zero) === this.Betwixt.after("");
});
});
describe("before", function() {
Given(function() {
return this.decrement = "\u1233";
});
it("should throw an error if its parameter is zero/empty", function() {
expect(function() {
return Betwixt.before(zero);
}).toThrowError(Error);
return expect(function() {
return Betwixt.before("");
}).toThrowError(Error);
});
describe("before treats the first non-zero character code as an integer and decrements it", function() {
Then(function() {
return this.Betwixt.before(this.start) === this.decrement;
});
return Then(function() {
return this.Betwixt.before(this.zero + this.start) === this.zero + this.decrement;
});
});
describe("before throws away anything after the decremented character", function() {
Then(function() {
return this.Betwixt.before(this.start + this.extra) === this.decrement;
});
return Then(function() {
return this.Betwixt.before(this.zero + this.start + this.extra) === this.zero + this.decrement;
});
});
return describe("if the decrement of the character is @zero, then before appends @Betwixt.midpoint() to the string", function() {
Then(function() {
return this.Betwixt.before("\u0001") === this.zero + this.Betwixt.midpoint();
});
return Then(function() {
return this.Betwixt.before(this.zero + "\u0001") === this.zero + this.zero + this.Betwixt.midpoint();
});
});
});
return describe("after", function() {
Given(function() {
return this.increment = "\u1235";
});
describe("before treats the first non-0xffff character code as an integer and decrements it", function() {
Then(function() {
return this.Betwixt.after(this.start) === this.increment;
});
return Then(function() {
return this.Betwixt.after(this.ffff + this.start) === this.ffff + this.increment;
});
});
describe("after throws away anything after the incremented character", function() {
Then(function() {
return this.Betwixt.after(this.start + this.extra) === this.increment;
});
return Then(function() {
return this.Betwixt.after(this.ffff + this.start + this.extra) === this.ffff + this.increment;
});
});
return describe("When the entire string consists of 0xffff characters, after appends a 0x8000 character to the string", function() {
return Then(function() {
return this.Betwixt.after(this.ffff + this.ffff) === this.ffff + this.ffff + "\u8000";
});
});
});
});
return describe("between()", function() {
Given(function() {
return this.a = "\u2001";
});
Given(function() {
return this.b = "\u2002";
});
Given(function() {
return this.c = "\u2003";
});
describe("between trims its arguments", function() {
return Then(function() {
return this.Betwixt.between(this.zero, this.zero + this.zero) === "";
});
});
describe("Betwixt.between(x,x) returns x", function() {
return Then(function() {
return this.Betwixt.between(this.a, this.a) === this.a;
});
});
describe("when possible, the fractions are averaged", function() {
Then(function() {
return this.Betwixt.between(this.a, this.c) === this.b;
});
return Then(function() {
var ref;
return (this.a < (ref = this.Betwixt.between(this.a, this.c)) && ref < this.c);
});
});
describe("the order of operands doesn't matter", function() {
Then(function() {
return this.Betwixt.between(this.b, this.a) === this.Betwixt.between(this.a, this.b);
});
return Then(function() {
return this.Betwixt.between(this.c, this.a) === this.Betwixt.between(this.a, this.c);
});
});
describe("slightly less easy parts", function() {
Given(function() {
return this.aa = this.a + "\u3333";
});
Given(function() {
return this.cc = this.c + "\uffff";
});
describe("If the two characters that first differ can be averaged, anything after them is ignored", function() {
return Then(function() {
return this.Betwixt.between(this.aa, this.cc) === this.b;
});
});
return describe("Strings with leading identical characters do the work after the leading characters", function() {
Given(function() {
return this.prefix = "\uaaaa\ubbbb\ucccc";
});
return Then(function() {
return this.Betwixt.between(this.prefix + this.aa, this.prefix + this.cc) === this.prefix + this.Betwixt.between(this.aa, this.cc);
});
});
});
describe("When the strings are the same length and their last characters differ only by one, the result is the prefix of the lesser string, extended by Betwixt.midpoint()", function() {
Then(function() {
return this.Betwixt.between(this.a, this.b) === "\u2001\u8000";
});
return Then(function() {
var ref;
return (this.a < (ref = this.Betwixt.between(this.a, this.b)) && ref < this.b);
});
});
describe("When the first differing characters differ only by one, and the greater string t has more characters, the result is the prefix of t up to and including the first differing character", function() {
Given(function() {
return this.lo = "\uaaaa\u1234";
});
Given(function() {
return this.hi = "\uaaaa\u1235\ubbb0";
});
return Then(function() {
return this.Betwixt.between(this.hi, this.lo) === "\uaaaa\u1235";
});
});
describe("When the lesser string s has more characters than the greater, consider the first differing character c, and the next character d. The between method returns the prefix of s up to and including c, concatenated with a character midway between d and 2**16.", function() {
Given(function() {
return this.lo = "\uaaaa\u1234\ubbbb\u9999";
});
Given(function() {
return this.hi = "\uaaaa\u1235";
});
return Then(function() {
return this.Betwixt.between(this.lo, this.hi) === "\uaaaa\u1234\udddd";
});
});
describe("But if character d is 0xffff (2**16-1), then we can't find a character between it and 2**16. So we need to extend our prefix to include c and the longest sequence of 0xffff characters immediately following c. Then d is the character after all of those.", function() {
Given(function() {
return this.lo = "\uaaaa\u1234\uffff\uffff\ubbbb\u9999";
});
Given(function() {
return this.hi = "\uaaaa\u1235";
});
return Then(function() {
return this.Betwixt.between(this.lo, this.hi) === "\uaaaa\u1234\uffff\uffff\udddd";
});
});
describe("Furthermore, if *every* character after c is 0xffff, then we append 0x8000 to s itself.", function() {
Given(function() {
return this.lo = "\uaaaa\u1234\uffff\uffff";
});
Given(function() {
return this.hi = "\uaaaa\u1235";
});
return Then(function() {
return this.Betwixt.between(this.hi, this.lo) === "\uaaaa\u1234\uffff\uffff\u8000";
});
});
return describe("If s is a prefix of t, then between acts as if s were extended by a ZERO character.", function() {
Given(function() {
return this.lo = "\uaaaa";
});
Given(function() {
return this.hi = "\uaaaa\u8000";
});
Given(function() {
return this.just_higher = "\uaaaa\u0001";
});
Then(function() {
return this.Betwixt.between(this.lo, this.hi) === "\uaaaa\u4000";
});
return Then(function() {
return this.Betwixt.between(this.lo, this.just_higher) === "\uaaaa\u0000\u8000";
});
});
});
});
}).call(this);