Share common lerp requirement checks.
[string-lerp.git] / tests / string-lerp.js
1 var JS = this.JS || require('jstest');
2 var stringLerp = require('../string-lerp');
3
4 var HALF_POOS = /\uD83D\uD83D|\uDCA9\uDCA9|\uD83D$/;
5 var UNUSUAL_Q = 'q\u0307\u0323';
6 var A = "Do you like green eggs and ham?";
7 var B = "I do not like them, Sam-I-am.";
8
9 function itHandlesBaseCases (parent, lerp) { with (parent) {
10 it("handles empty strings", function () { with (this) {
11 assertEqual("", lerp("", "", -1));
12 assertEqual("", lerp("", "", 0));
13 assertEqual("", lerp("", "", 0.5));
14 assertEqual("", lerp("", "", 1));
15 assertEqual("", lerp("", "", 2));
16 }});
17
18 it("maintains identity", function () { with (this) {
19 for (var i = -1; i < 2; i += 1/1024) {
20 assertEqual(A, lerp(A, A, i));
21 assertEqual(B, lerp(B, B, i));
22 }
23 }});
24 }}
25
26 function itMakesValidStrings (parent, lerp) { with (parent) {
27 it("doesn't make half a poo", function () { with (this) {
28 var poos = "\uD83D\uDCA9\uD83D\uDCA9\uD83D\uDCA9\uD83D\uDCA9";
29 assertEqual("\uD83D\uDCA9\uD83D\uDCA9", lerp("", poos, 0.5));
30 assertEqual("\uD83D\uDCA9", lerp("", poos, 0.35));
31
32 for (var i = 0; i <= 1; i += 1/256)
33 assertNot(lerp("", poos, i).match(HALF_POOS));
34 }});
35
36 it("doesn't misplace combining marks", function () { with (this) {
37 for (var i = 0; i <= 1; i += 1/256) {
38 var r = lerp("a", UNUSUAL_Q, i);
39 assert(r === "a" || r === UNUSUAL_Q);
40 }
41 }});
42 }}
43
44 function itDoesntOvershoot (parent, lerp) { with (parent) {
45 it("handles lows", function () { with (this) {
46 assertEqual(A, lerp(A, B, -Infinity));
47 assertEqual(A, lerp(A, B, -1));
48 assertEqual(A, lerp(A, B, 0));
49 }});
50
51 it("handles highs", function () { with (this) {
52 assertEqual(B, lerp(A, B, 1));
53 assertEqual(B, lerp(A, B, 2));
54 assertEqual(B, lerp(A, B, Infinity));
55 }});
56 }}
57
58 JS.Test.describe('fast lerp', function () { with (this) {
59 var lerp = stringLerp.fastLerp;
60
61 itHandlesBaseCases(this, lerp);
62 itMakesValidStrings(this, lerp);
63 itDoesntOvershoot(this, lerp);
64
65 it("crams strings together", function () { with (this) {
66 assertEqual("I do not ke green eggs and ham?", lerp(A, B, 0.3));
67 assertEqual("I do not like tn eggs and ham?", lerp(A, B, 0.5));
68 assertEqual("I do not like them, Sam-I-am?", lerp(A, B, 0.98));
69 }});
70
71 }});
72
73 function itEditsHumanly(parent, lerp) { with (parent) {
74 it("edits strings", function () { with (this) {
75 assertEqual(A, lerp(A, B, 0.01));
76 assertEqual("I do not like treen eggs and ham?", lerp(A, B, 0.3));
77 assertEqual("I do not like them, eggs and ham?", lerp(A, B, 0.5));
78 assertEqual("I do not like them, Sam-Iham?", lerp(A, B, 0.9));
79 assertEqual(B, lerp(A, B, 0.99));
80 }});
81
82 it("prefers ins/del to sub/sub", function () { with (this) {
83 // When the cost is uniform this string can be transformed by
84 // rewriting the whole thing for the same cost as deleting the
85 // front and adding to the back. But visually, we'd rather do
86 // the latter.
87 assertEqual("core", lerp("hard core", "core dump", 0.50));
88 }});
89
90 it("weights ins/del cheaper than sub", function () { with (this) {
91 // When the cost is uniform it is cheaper to rewrite the
92 // former into the latter. But we'd rather keep the "core" for
93 // visual reasons, so we need to make sure we have unequal
94 // costs.
95 assertEqual("core", lerp("apple core", "core dump", 0.51));
96 }});
97 }}
98
99 JS.Test.describe('diff lerp', function () { with (this) {
100 var lerp = stringLerp.diffLerp;
101
102 itHandlesBaseCases(this, lerp);
103 itMakesValidStrings(this, lerp);
104 itDoesntOvershoot(this, lerp);
105 itEditsHumanly(this, lerp);
106 }});
107
108 function itTreatsNumeralsAsNumbers(parent, lerp) { with (parent) {
109 it("handles single numbers", function () { with (this) {
110 assertEqual("0", lerp("0", "100", 0));
111 assertEqual("50", lerp("0", "100", 0.5));
112 assertEqual("100", lerp("0", "100", 1.0));
113 assertEqual("150", lerp("0", "100", 1.5));
114 }});
115
116 it("rounds integers", function () { with (this) {
117 assertEqual("12", lerp("0", "100", 0.123));
118 assertEqual("12.3", lerp("0.0", "100.0", 0.123));
119 assertEqual("12.3", lerp("0.0", "100", 0.123));
120 assertEqual("12.3", lerp("0.0", "100.0", 0.123));
121 }});
122
123 it("thinks about precision", function () { with (this) {
124 assertEqual("12.30", lerp("0.00", "100.00", 0.123));
125 assertEqual("12.300", lerp("0.000", "100.000", 0.123));
126 }});
127
128 it("computes parameters outside [0, 1]", function () { with (this) {
129 assertEqual("Giving 110%", lerp("Giving 0%", "Giving 100%", 1.1));
130 }});
131
132 it("handles multiple numbers", function () { with (this) {
133 var A = "Chapter 0. The sky was rgb(0, 0, 0).";
134 var B = "Chapter 10. The sky was rgb(0, 0, 255).";
135 assertEqual(A, lerp(A, B, 0));
136 assertEqual(B, lerp(A, B, 1));
137 assertEqual("Chapter 5. The sky was rgb(0, 0, 128).", lerp(A, B, 0.5));
138 }});
139 }}
140
141 JS.Test.describe('numeric lerp', function () { with (this) {
142 var lerp = stringLerp.numericLerp;
143
144 itHandlesBaseCases(this, lerp);
145 itTreatsNumeralsAsNumbers(this, lerp);
146 }});
147
148 JS.Test.describe('auto lerp', function () { with (this) {
149 var lerp = stringLerp.lerp;
150
151 itHandlesBaseCases(this, lerp);
152 itMakesValidStrings(this, lerp);
153 itDoesntOvershoot(this, lerp);
154 itTreatsNumeralsAsNumbers(this, lerp);
155 itEditsHumanly(this, lerp);
156 }});