Add tests and build scripts.
authorJoe Wreschnig <joe.wreschnig@gmail.com>
Tue, 13 May 2014 17:04:33 +0000 (19:04 +0200)
committerJoe Wreschnig <joe.wreschnig@gmail.com>
Tue, 13 May 2014 17:04:33 +0000 (19:04 +0200)
.gitignore [new file with mode: 0644]
Makefile [new file with mode: 0644]
demo.html
string-lerp.js
tests/string-lerp.js [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..c169afd
--- /dev/null
@@ -0,0 +1,3 @@
+build
+node_modules
+*.min.js
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..5dfff02
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,54 @@
+#!/usr/bin/make -f
+
+JSTEST ?= node_modules/.bin/jstest
+JSHINT ?= node_modules/.bin/jshint
+UGLIFY ?= node_modules/.bin/uglifyjs
+SOURCES = string-lerp.js
+MINIFIED = $(SOURCES:.js=.min.js)
+
+TESTS = $(wildcard tests/*.js);
+LINT_TARGETS = $(addprefix build/stamp/,$(addsuffix .lint,$(SOURCES)))
+TEST_TARGETS = $(addprefix build/stamp/,$(addsuffix .test,$(SOURCES)))
+
+.PHONY: all check lint test
+
+all: $(MINIFIED)
+
+%.min.js: %.js $(UGLIFY)
+       $(UGLIFY) -m < $< > $@
+
+build:
+       mkdir -p build/stamp build/dist
+
+build/stamp/%.lint: % build
+       @mkdir -p $(@D)
+       $(JSHINT) $<
+       @touch $@
+
+build/stamp/%.test: tests/% % build
+       @mkdir -p $(@D)
+       @echo $(JSTEST) $<
+       @$(JSTEST) $< > $@ || (cat $@ && rm -f $@ && exit 1)
+       @touch $@
+
+check: lint test
+
+lint: $(JSHINT) $(LINT_TARGETS)
+
+test: $(JSTEST) $(TEST_TARGETS)
+
+clean:
+       rm -rf build
+       rm -f $(MINIFIED)
+
+distclean: clean
+       rm -rf node_modules
+
+$(JSTEST):
+       npm install jstest
+
+$(JSHINT):
+       npm install jshint
+
+$(UGLIFY):
+       npm install uglify-js
index c8712c9..8506eb7 100644 (file)
--- a/demo.html
+++ b/demo.html
@@ -23,8 +23,8 @@
   </head>
   <body onload="update(0.5)">
     <div style="width: 70%; margin: 3em auto; column-spacing: 10%;">
   </head>
   <body onload="update(0.5)">
     <div style="width: 70%; margin: 3em auto; column-spacing: 10%;">
-      <input type="text" id="a" value="source text">
-      <input type="text" id="b" value="target text">
+      <input type="text" id="a" value="Do you like green eggs and ham?">
+      <input type="text" id="b" value="I do not like them, Sam-I-am.">
     </div>
     <div id="text" style="font-size: 3em; text-align: center;"></div>
     <input type="range" value=0.5 max=1.00 step=0.00390625 oninput="update(this.value);"
     </div>
     <div id="text" style="font-size: 3em; text-align: center;"></div>
     <input type="range" value=0.5 max=1.00 step=0.00390625 oninput="update(this.value);"
index 8d5a879..5e8201c 100644 (file)
@@ -31,7 +31,7 @@
 
     function editPath(d, t) {
         /** Given a Levenshtein matrix and target, create an edit list */
 
     function editPath(d, t) {
         /** Given a Levenshtein matrix and target, create an edit list */
-        var path = []
+        var path = [];
         var j = t.length;
         var n = j + 1;
         var i = d.length / n - 1;
         var j = t.length;
         var n = j + 1;
         var i = d.length / n - 1;
@@ -93,7 +93,7 @@
         return patch(partial, a);
     }
 
         return patch(partial, a);
     }
 
-    var NUMBERS = /(-?\d+(?:\.\d+)?)/g
+    var NUMBERS = /(-?\d+(?:\.\d+)?)/g;
 
     function areNumericTwins(a, b) {
         /** Check if a and b differ only in numerals
 
     function areNumericTwins(a, b) {
         /** Check if a and b differ only in numerals
         var aParts = a.split(NUMBERS);
         var bParts = b.split(NUMBERS);
         for (var i = 1; i < aParts.length; i += 2) {
         var aParts = a.split(NUMBERS);
         var bParts = b.split(NUMBERS);
         for (var i = 1; i < aParts.length; i += 2) {
-            var part = nlerp(+aParts[i], +bParts[i], p)
+            var part = nlerp(+aParts[i], +bParts[i], p);
             if (aParts[i].indexOf(".") === -1 && bParts[i].indexOf(".") === -1)
                 part = Math.round(part);
             aParts[i] = part.toString();
             if (aParts[i].indexOf(".") === -1 && bParts[i].indexOf(".") === -1)
                 part = Math.round(part);
             aParts[i] = part.toString();
         if (p === 1) return b;
 
         if (areNumericTwins(a, b))
         if (p === 1) return b;
 
         if (areNumericTwins(a, b))
-            return numericLerp(a, b, p)
+            return numericLerp(a, b, p);
 
         // Numeric lerps should over- and under-shoot when fed numbers
         // outside 0 to 1, but other types cannot.
 
         // Numeric lerps should over- and under-shoot when fed numbers
         // outside 0 to 1, but other types cannot.
         if (p > 1) return b;
 
         var n = a.length * b.length;
         if (p > 1) return b;
 
         var n = a.length * b.length;
-        return (n && n < MAX_MATRIX_SIZE)
-            ? diffLerp(a, b, p)
-            : fastLerp(a, b, p);
+        return ((n && n < MAX_MATRIX_SIZE) ? diffLerp : fastLerp)(a, b, p);
     }
 
     exports.levenshteinMatrix = levenshteinMatrix;
     }
 
     exports.levenshteinMatrix = levenshteinMatrix;
diff --git a/tests/string-lerp.js b/tests/string-lerp.js
new file mode 100644 (file)
index 0000000..2e7f01f
--- /dev/null
@@ -0,0 +1,118 @@
+var JS = this.JS || require('jstest');
+var m = require('../string-lerp');
+
+JS.Test.describe('fast lerp', function () { with (this) {
+    var lerp = m.fastLerp;
+    var A = "Do you like green eggs and ham?";
+    var B = "I do not like them, Sam-I-am.";
+
+    it("handles empty strings", function () { with (this) {
+        assertEqual("", lerp("", "", -1));
+        assertEqual("", lerp("", "", 0));
+        assertEqual("", lerp("", "", 0.5));
+        assertEqual("", lerp("", "", 1));
+        assertEqual("", lerp("", "", 2));
+    }});
+
+    it("maintains identity", function () { with (this) {
+        for (var i = -1; i < 2; i += 1/1024) {
+            assertEqual(A, lerp(A, A, i));
+            assertEqual(B, lerp(B, B, i));
+        }
+    }});
+
+    it("handles lows", function () { with (this) {
+        assertEqual(A, lerp(A, B, -Infinity));
+        assertEqual(A, lerp(A, B, -1));
+        assertEqual(A, lerp(A, B, 0));
+    }});
+
+    it("handles highs", function () { with (this) {
+        assertEqual(B, lerp(A, B, 1));
+        assertEqual(B, lerp(A, B, 2));
+        assertEqual(B, lerp(A, B, Infinity));
+    }});
+
+    it("crams strings together", function () { with (this) {
+        assertEqual("I do not ke green eggs and ham?", lerp(A, B, 0.3));
+        assertEqual("I do not like tn eggs and ham?", lerp(A, B, 0.5));
+        assertEqual("I do not like them, Sam-I-am?", lerp(A, B, 0.98));
+    }});
+}});
+
+JS.Test.describe('diff lerp', function () { with (this) {
+    var lerp = m.diffLerp;
+    var A = "Do you like green eggs and ham?";
+    var B = "I do not like them, Sam-I-am.";
+
+    it("handles empty strings", function () { with (this) {
+        assertEqual("", lerp("", "", -1));
+        assertEqual("", lerp("", "", 0));
+        assertEqual("", lerp("", "", 0.5));
+        assertEqual("", lerp("", "", 1));
+        assertEqual("", lerp("", "", 2));
+    }});
+
+    it("maintains identity", function () { with (this) {
+        for (var i = -1; i < 2; i += 1/1024) {
+            assertEqual(A, lerp(A, A, i));
+            assertEqual(B, lerp(B, B, i));
+        }
+    }});
+
+    it("handles lows", function () { with (this) {
+        assertEqual(A, lerp(A, B, -Infinity));
+        assertEqual(A, lerp(A, B, -1));
+        assertEqual(A, lerp(A, B, 0));
+    }});
+
+    it("handles highs", function () { with (this) {
+        assertEqual(B, lerp(A, B, 1));
+        assertEqual(B, lerp(A, B, 2));
+        assertEqual(B, lerp(A, B, Infinity));
+    }});
+
+    it("edits strings", function () { with (this) {
+        assertEqual("Do you like green eggsSam-I-am.", lerp(A, B, 0.3));
+        assertEqual("Do you like green Sam-I-am.", lerp(A, B, 0.5));
+        assertEqual("do not like them, Sam-I-am.", lerp(A, B, 0.9));
+    }});
+}});
+
+JS.Test.describe('numeric lerp', function () { with (this) {
+    var lerp = m.numericLerp;
+
+    it("handles empty strings", function () { with (this) {
+        assertEqual("", lerp("", "", -1));
+        assertEqual("", lerp("", "", 0));
+        assertEqual("", lerp("", "", 0.5));
+        assertEqual("", lerp("", "", 1));
+        assertEqual("", lerp("", "", 2));
+    }});
+
+    it("handles single numbers", function () { with (this) {
+        assertEqual("0", lerp("0", "100", 0));
+        assertEqual("50", lerp("0", "100", 0.5));
+        assertEqual("100", lerp("0", "100", 1.0));
+        assertEqual("150", lerp("0", "100", 1.5));
+    }});
+
+    it("rounds integers", function () { with (this) {
+        assertEqual("12", lerp("0", "100", 0.123));
+        assertEqual("12.3", lerp("0", "100.0", 0.123));
+        assertEqual("12.3", lerp("0.0", "100", 0.123));
+        assertEqual("12.3", lerp("0.0", "100.0", 0.123));
+    }});
+
+    it("computes parameters outside [0, 1]", function () { with (this) {
+        assertEqual("Giving 110%", lerp("Giving 0%", "Giving 100%", 1.1));
+    }});
+
+    it("handles multiple numbers", function () { with (this) {
+        var A = "Chapter 0. The sky was rgb(0, 0, 0)."
+        var B = "Chapter 10. The sky was rgb(0, 0, 255)."
+        assertEqual(A, lerp(A, B, 0));
+        assertEqual(B, lerp(A, B, 1));
+        assertEqual("Chapter 5. The sky was rgb(0, 0, 128).", lerp(A, B, 0.5));
+    }});
+}});