Skip to content
Browse files

Finished up test harnesses for node and browser

  • Loading branch information...
1 parent 3d23611 commit 6b775dbe58af9c4aa4f9fd593187fd48627757b1 @tautologistics committed
Showing with 623 additions and 543 deletions.
  1. +1 −1 LICENSE
  2. +9 −19 lib/htmlparser.js
  3. +2 −2 package.json
  4. +208 −77 runtests.html
  5. +114 −157 runtests.js
  6. +31 −19 tests/html.js
  7. +32 −249 tests/parser.js
  8. +31 −19 tests/rss.js
  9. +195 −0 tests/testutils.js
View
2 LICENSE
@@ -1,4 +1,4 @@
-Copyright 2010, 2011, Chris Winberry <chris@winberry.net>. All rights reserved.
+Copyright 2010 - 2012, Chris Winberry <chris@winberry.net>. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
View
28 lib/htmlparser.js
@@ -22,28 +22,18 @@ IN THE SOFTWARE.
(function () {
-function runningInNode () {
- return(
- (typeof require) == "function"
- &&
- (typeof exports) == "object"
- &&
- (typeof module) == "object"
- &&
- (typeof __filename) == "string"
- &&
- (typeof __dirname) == "string"
- );
-}
-
-if (!runningInNode()) {
+var exports;
+if (typeof(module) !== 'undefined' && typeof(module.exports) !== 'undefined') {
+ exports = module.exports;
+} else {
+ exports = {};
if (!this.Tautologistics) {
this.Tautologistics = {};
- } else if (this.Tautologistics.NodeHtmlParser) {
- return; //NodeHtmlParser already defined!
}
- this.Tautologistics.NodeHtmlParser = {};
- exports = this.Tautologistics.NodeHtmlParser;
+ if (this.Tautologistics.NodeHtmlParser) {
+ return;
+ }
+ this.Tautologistics.NodeHtmlParser = exports;
}
function inherits (ctor, superCtor) {
View
4 package.json
@@ -1,7 +1,7 @@
{
"name": "htmlparser"
, "description": "Forgiving HTML/XML/RSS Parser in JS for *both* Node and Browsers"
- , "version": "1.7.6"
+ , "version": "2.0.0"
, "author": "Chris Winberry <chris@winberry.net>"
, "contributors": []
, "repository": {
@@ -25,7 +25,7 @@
}
, "directories": { "lib": "./lib/" }
, "main": "./lib/htmlparser"
- , "engines": { "node": ">=0.1.33" }
+ , "engines": { "node": ">=0.5.0" }
, "licenses": [{
"type": "MIT"
, "url": "http://github.com/tautologistics/node-htmlparser/raw/master/LICENSE"
View
285 runtests.html
@@ -1,13 +1,37 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--
+Copyright 2010 - 2012, Chris Winberry <chris@winberry.net>. All rights reserved.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
+-->
+
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Node.js HTML Parser</title>
<style type="text/css">
- .good {
+ .testName {
+ font-weight: bold;
+ }
+ .pass {
color: #363;
}
- .bad {
+ .fail {
color: #633;
font-style: italic;
}
@@ -22,87 +46,194 @@
}
</script>
<script language="JavaScript" src="lib/htmlparser.js"></script>
- <script language="JavaScript" src="tests/01-basic.js"></script>
- <script language="JavaScript" src="tests/02-single_tag_1.js"></script>
- <script language="JavaScript" src="tests/03-single_tag_2.js"></script>
- <script language="JavaScript" src="tests/04-unescaped_in_script.js"></script>
- <script language="JavaScript" src="tests/05-tags_in_comment.js"></script>
- <script language="JavaScript" src="tests/06-comment_in_script.js"></script>
- <script language="JavaScript" src="tests/07-unescaped_in_style.js"></script>
- <script language="JavaScript" src="tests/08-extra_spaces_in_tag.js"></script>
- <script language="JavaScript" src="tests/09-unquoted_attrib.js"></script>
- <script language="JavaScript" src="tests/10-singular_attribute.js"></script>
- <script language="JavaScript" src="tests/11-text_outside_tags.js"></script>
- <script language="JavaScript" src="tests/12-text_only.js"></script>
- <script language="JavaScript" src="tests/13-comment_in_text.js"></script>
- <script language="JavaScript" src="tests/14-comment_in_text_in_script.js"></script>
- <script language="JavaScript" src="tests/15-non-verbose.js"></script>
- <script language="JavaScript" src="tests/16-ignore_whitespace.js"></script>
- <script language="JavaScript" src="tests/17-xml_namespace.js"></script>
- <script language="JavaScript" src="tests/18-enforce_empty_tags.js"></script>
- <script language="JavaScript" src="tests/19-ignore_empty_tags.js"></script>
- <script language="JavaScript" src="tests/20-rss.js"></script>
- <script language="JavaScript" src="tests/21-atom.js"></script>
- <script language="JavaScript" src="tests/22-position_data.js"></script>
+ <script language="JavaScript" src="tests/testutils.js"></script>
+ <script language="JavaScript" src="tests/html.js"></script>
+ <script language="JavaScript" src="tests/parser.js"></script>
+ <script language="JavaScript" src="tests/rss.js"></script>
<!-- //TODO: dynamic loading of test files -->
</head>
<body style="font-size: small; font-family:Arial, Helvetica, sans-serif;">
<script language="JavaScript">
- var chunkSize = 5;
- var testCount = 0;
- var failedCount = 0;
- while (Tautologistics.NodeHtmlParser.Tests.length) {
- testCount++;
- var test = Tautologistics.NodeHtmlParser.Tests.shift();
- try {
- var handlerCallback = function handlerCallback (error) {
- if (error)
- document.write("<hr>Handler error: " + error + "<hr>");
- }
- var handler = (test.type == "rss") ?
- new Tautologistics.NodeHtmlParser.RssHandler(handlerCallback, test.options.handler)
- :
- new Tautologistics.NodeHtmlParser.DefaultHandler(handlerCallback, test.options.handler)
- ;
- var parser = new Tautologistics.NodeHtmlParser.Parser(handler, test.options.parser);
- document.write("<b>" + test.name + "</b>: ");
- parser.parseComplete(test.html);
- var resultComplete = handler.dom;
- var chunkPos = 0;
- parser.reset();
- while (chunkPos < test.html.length) {
- parser.parseChunk(test.html.substring(chunkPos, chunkPos + chunkSize));
- chunkPos += chunkSize;
- }
- parser.done();
- var resultChunk = handler.dom;
- var testResult =
- JSON.stringify(resultComplete).toString() === JSON.stringify(test.expected).toString()
- &&
- JSON.stringify(resultChunk).toString() === JSON.stringify(test.expected).toString()
- ;
- document.write(testResult ? "<font class='good'>passed</font>" : "<font class='bad'>FAILED</font>");
- if (!testResult) {
- failedCount++;
- document.write("<pre>");
- document.write("<b>Complete</b>\n");
- document.write(JSON.stringify(resultComplete, null, 2));
- document.write("<b>Chunked</b>\n");
- document.write(JSON.stringify(resultChunk, null, 2));
- document.write("<h2>Expected</h2>\n");
- document.write(JSON.stringify(test.expected, null, 2));
- document.write("</pre>");
- }
- } catch (ex) {
- document.write("<h1>Exception occured during test: " + ex + "</h1>")
- }
- document.write("<br>");
+ (function () {
+
+ function writeTest (name, result) {
+ document.write(
+ "<div>" +
+ "<span class='testName'>" + name + "</span>: " +
+ "<span class='" + (result ? 'pass' : 'fail') + "'>" + (result ? 'passed' : 'FAILED') + "</span>" +
+ "</div>"
+ );
}
- document.write("<hr>");
- document.write("Total tests: " + testCount + "<br>");
- document.write("Failed tests: " + failedCount + "<br>");
+
+ var testResults = {};
+
+ Tautologistics.NodeHtmlParser.Tests.Utils.runBuilderTests(
+ Tautologistics.NodeHtmlParser.Tests.Html
+ , Tautologistics.NodeHtmlParser.Parser
+ , Tautologistics.NodeHtmlParser.HtmlBuilder
+ , null
+ , function (testName, testResult, actual, expected) {
+ // console.log("[" + testName + "]: " + (testResult ? "passed" : "FAILED"));
+ writeTest(testName, testResult);
+ }, function (elapsed, passed, failed) {
+ testResults['HTML builder'] = {
+ elapsed: elapsed
+ , passed: passed
+ , failed: failed
+ };
+ });
+ Tautologistics.NodeHtmlParser.Tests.Utils.runBuilderTests(
+ Tautologistics.NodeHtmlParser.Tests.Html
+ , Tautologistics.NodeHtmlParser.Parser
+ , Tautologistics.NodeHtmlParser.HtmlBuilder
+ , function (test) {
+ var newTest = {};
+ for (var key in test) {
+ if (!test.hasOwnProperty(key)) {
+ continue;
+ }
+ newTest[key] = (key === 'data') ?
+ test.data.join('').split('')
+ :
+ test[key]
+ ;
+ }
+ return newTest;
+ }
+ , function (testName, testResult, actual, expected) {
+ // console.log("[" + testName + "]: " + (testResult ? "passed" : "FAILED"));
+ writeTest(testName, testResult);
+ }, function (elapsed, passed, failed) {
+ testResults['HTML builder (streamed)'] = {
+ elapsed: elapsed
+ , passed: passed
+ , failed: failed
+ };
+ });
+
+ Tautologistics.NodeHtmlParser.Tests.Utils.runBuilderTests(
+ Tautologistics.NodeHtmlParser.Tests.Rss
+ , Tautologistics.NodeHtmlParser.Parser
+ , Tautologistics.NodeHtmlParser.RssBuilder
+ , null
+ , function (testName, testResult, actual, expected) {
+ // console.log("[" + testName + "]: " + (testResult ? "passed" : "FAILED"));
+ writeTest(testName, testResult);
+ }, function (elapsed, passed, failed) {
+ testResults['RSS builder'] = {
+ elapsed: elapsed
+ , passed: passed
+ , failed: failed
+ };
+ });
+ Tautologistics.NodeHtmlParser.Tests.Utils.runBuilderTests(
+ Tautologistics.NodeHtmlParser.Tests.Rss
+ , Tautologistics.NodeHtmlParser.Parser
+ , Tautologistics.NodeHtmlParser.RssBuilder
+ , function (test) {
+ var newTest = {};
+ for (var key in test) {
+ if (!test.hasOwnProperty(key)) {
+ continue;
+ }
+ newTest[key] = (key === 'data') ?
+ test.data.join('').split('')
+ :
+ test[key]
+ ;
+ }
+ return newTest;
+ }
+ , function (testName, testResult, actual, expected) {
+ // console.log("[" + testName + "]: " + (testResult ? "passed" : "FAILED"));
+ writeTest(testName, testResult);
+ }, function (elapsed, passed, failed) {
+ testResults['RSS builder (streamed)'] = {
+ elapsed: elapsed
+ , passed: passed
+ , failed: failed
+ };
+ });
+
+ Tautologistics.NodeHtmlParser.Tests.Utils.runParserTests(
+ Tautologistics.NodeHtmlParser.Tests.Parser
+ , Tautologistics.NodeHtmlParser.Parser
+ , null
+ , function (testName, testResult, actual, expected) {
+ // console.log("[" + testName + "]: " + (testResult ? "passed" : "FAILED"));
+ writeTest(testName, testResult);
+ }, function (elapsed, passed, failed) {
+ testResults['Parser'] = {
+ elapsed: elapsed
+ , passed: passed
+ , failed: failed
+ };
+ });
+ Tautologistics.NodeHtmlParser.Tests.Utils.runParserTests(
+ Tautologistics.NodeHtmlParser.Tests.Parser
+ , Tautologistics.NodeHtmlParser.Parser
+ , function (test) {
+ var newTest = {};
+ for (var key in test) {
+ if (!test.hasOwnProperty(key)) {
+ continue;
+ }
+ newTest[key] = (key === 'data') ?
+ test.data.join('').split('')
+ :
+ test[key]
+ ;
+ }
+ return newTest;
+ }
+ , function (testName, testResult, actual, expected) {
+ // console.log("[" + testName + "]: " + (testResult ? "passed" : "FAILED"));
+ writeTest(testName, testResult);
+ }, function (elapsed, passed, failed) {
+ testResults['Parser (streamed)'] = {
+ elapsed: elapsed
+ , passed: passed
+ , failed: failed
+ };
+ });
+
+ document.write(
+ "<br>" +
+ '<h1>Test Results</h1>' +
+ '<hr>'
+ );
+ var passedTotal = 0;
+ var failedTotal = 0;
+ var elapsedTotal = 0;
+ for (var testName in testResults) {
+ if (!testResults.hasOwnProperty(testName)) {
+ continue;
+ }
+ var test = testResults[testName];
+ passedTotal += test.passed;
+ failedTotal += test.failed;
+ elapsedTotal += test.elapsed;
+ document.write(
+ "<div>" +
+ "<span class='testName'>" + testName + '</span>: ' +
+ "<span class='" + (test.failed === 0 ? 'pass' : 'fail') + "'>" +
+ test.passed + '/' + (test.passed + test.failed) +
+ ' (' + Math.round(test.passed / (test.passed + test.failed) * 100) + '%) ' +
+ '[' + test.elapsed + 'ms]' +
+ "</span>" +
+ "</div>"
+ );
+ }
+ document.write(
+ '<hr>' +
+ 'Total: ' + passedTotal + '/' + (passedTotal + failedTotal) +
+ ' (' + Math.round(passedTotal / (passedTotal + failedTotal) * 100) + '%) ' +
+ '[' + elapsedTotal + 'ms]'
+ );
+
+ })();
</script>
-
+
</body>
</html>
View
271 runtests.js
@@ -1,5 +1,5 @@
/***********************************************
-Copyright 2010, Chris Winberry <chris@winberry.net>. All rights reserved.
+Copyright 2010 - 2012, Chris Winberry <chris@winberry.net>. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
@@ -73,179 +73,136 @@ var util = require("util");
var fs = require("fs");
var htmlparser = require("./lib/htmlparser");
+var testUtils = require('./tests/testutils');
var htmlTests = require('./tests/html');
var rssTests = require('./tests/rss');
var parserTests = require('./tests/parser');
-var testResults = {};
-
-function runBuilderTests (tests, builderCtor, permutator) {
- var passed = 0;
- var failed = 0;
-
- var builderCallback = function builderCallback (error) {
- if (error) {
- util.puts("Builder error: " + error);
- }
- };
-
- var startTime = Date.now();
- for (var testName in tests) {
- if (!tests.hasOwnProperty(testName)) {
- continue;
- }
- var test = permutator ? permutator(tests[testName]) : tests[testName];
- var builder = new builderCtor(builderCallback, test.options.builder);
- var parser = new htmlparser.Parser(builder, test.options.parser);
+var testResults = {};
- parser.reset();
- if (test.data.length === 1) {
- parser.parseComplete(test.data[0]);
- } else {
- for (var i = 0, len = test.data.length; i < len; i++) {
- parser.parseChunk(test.data[i]);
+testUtils.runBuilderTests(
+ htmlTests
+ , htmlparser.Parser
+ , htmlparser.HtmlBuilder
+ , null
+ , function (testName, testResult, actual, expected) {
+ console.log("[" + testName + "]: " + (testResult ? "passed" : "FAILED"));
+ }, function (elapsed, passed, failed) {
+ testResults['HTML builder'] = {
+ elapsed: elapsed
+ , passed: passed
+ , failed: failed
+ };
+ });
+testUtils.runBuilderTests(
+ htmlTests
+ , htmlparser.Parser
+ , htmlparser.HtmlBuilder
+ , function (test) {
+ var newTest = {};
+ for (var key in test) {
+ if (!test.hasOwnProperty(key)) {
+ continue;
}
- parser.done();
- }
- var testResult = builder.dom.equals(test.expected);
-
- util.puts("[" + testName + "]: " + (testResult ? "passed" : "FAILED"));
- if (!testResult) {
- failed++;
- // util.puts(util.inspect(builder._raw, false, null));
- util.puts("== Result ==");
- util.puts(util.inspect(builder.dom, false, null));
- util.puts("== Expected ==");
- util.puts(util.inspect(test.expected, false, null));
- } else {
- passed++;
+ newTest[key] = (key === 'data') ?
+ test.data.join('').split('')
+ :
+ test[key]
+ ;
}
+ return newTest;
}
- var endTime = Date.now();
-
- return {
- elapsed: endTime - startTime
+ , function (testName, testResult, actual, expected) {
+ console.log("[" + testName + "]: " + (testResult ? "passed" : "FAILED"));
+ }, function (elapsed, passed, failed) {
+ testResults['HTML builder (streamed)'] = {
+ elapsed: elapsed
, passed: passed
, failed: failed
- };
-}
-
-function TestBuilder (callback) {
- this.cb = callback;
- this.reset();
-}
-TestBuilder.prototype.reset = function () {
- this.output = [];
-}
-TestBuilder.prototype.write = function (element) {
- this.output.push(element);
-}
-TestBuilder.prototype.done = function () {
- this.cb(null, this.output);
-}
-TestBuilder.prototype.error = function (error) {
- this.cb(error);
-}
-
-function runParserTests (tests, permutator) {
- var callback = function builderCallback (err) {
- if (err) {
- console.log('Builder error', err);
- }
- };
- var builder = new TestBuilder(callback);
- var parser = new htmlparser.Parser(builder);
-
- var passed = 0;
- var failed = 0;
-
- var startTime = Date.now();
- for (var testName in tests) {
- if (!tests.hasOwnProperty(testName)) {
- continue;
- }
- var test = permutator ? permutator(tests[testName]) : tests[testName];
- process.stdout.write('[TEST] ' + testName + ' : ');
- parser.reset();
- if (test.data.length === 1) {
- parser.parseComplete(test.data[0]);
- } else {
- for (var i = 0, len = test.data.length; i < len; i++) {
- parser.parseChunk(test.data[i]);
+ };
+ });
+
+testUtils.runBuilderTests(
+ rssTests
+ , htmlparser.Parser
+ , htmlparser.RssBuilder
+ , null
+ , function (testName, testResult, actual, expected) {
+ console.log("[" + testName + "]: " + (testResult ? "passed" : "FAILED"));
+ }, function (elapsed, passed, failed) {
+ testResults['RSS builder'] = {
+ elapsed: elapsed
+ , passed: passed
+ , failed: failed
+ };
+ });
+testUtils.runBuilderTests(
+ rssTests
+ , htmlparser.Parser
+ , htmlparser.RssBuilder
+ , function (test) {
+ var newTest = {};
+ for (var key in test) {
+ if (!test.hasOwnProperty(key)) {
+ continue;
}
- parser.done();
- }
-
- var testResult = builder.output.equals(test.expected);
-
- if (!testResult) {
- failed++;
- process.stdout.write("FAILED\n");
- util.puts("== Result ==");
- util.puts(util.inspect(builder.output, false, null));
- util.puts("== Expected ==");
- util.puts(util.inspect(test.expected, false, null));
- } else {
- passed++;
- process.stdout.write("Ok\n");
+ newTest[key] = (key === 'data') ?
+ test.data.join('').split('')
+ :
+ test[key]
+ ;
}
+ return newTest;
}
- var endTime = Date.now();
-
- return {
- elapsed: endTime - startTime
+ , function (testName, testResult, actual, expected) {
+ console.log("[" + testName + "]: " + (testResult ? "passed" : "FAILED"));
+ }, function (elapsed, passed, failed) {
+ testResults['RSS builder (streamed)'] = {
+ elapsed: elapsed
, passed: passed
, failed: failed
- };
-}
-
-var testResults = {};
-
-testResults['HTML builder, single chunk'] = runBuilderTests(htmlTests, htmlparser.HtmlBuilder);
-testResults['HTML builder, streamed'] = runBuilderTests(htmlTests, htmlparser.HtmlBuilder, function (test) {
- var newTest = {};
- for (var key in test) {
- if (!test.hasOwnProperty(key)) {
- continue;
- }
- newTest[key] = (key === 'data') ?
- test.data.join('').split('')
- :
- test[key]
- ;
- }
- return newTest;
-});
-testResults['RSS builder, single chunk'] = runBuilderTests(rssTests, htmlparser.RssBuilder);
-testResults['RSS builder, streamed'] = runBuilderTests(rssTests, htmlparser.RssBuilder, function (test) {
- var newTest = {};
- for (var key in test) {
- if (!test.hasOwnProperty(key)) {
- continue;
- }
- newTest[key] = (key === 'data') ?
- test.data.join('').split('')
- :
- test[key]
- ;
- }
- return newTest;
-});
-testResults['Parser, single chunk'] = runParserTests(parserTests);
-testResults['Parser, streamed'] = runParserTests(parserTests, function (test) {
- var newTest = {};
- for (var key in test) {
- if (!test.hasOwnProperty(key)) {
- continue;
+ };
+ });
+
+testUtils.runParserTests(
+ parserTests
+ , htmlparser.Parser
+ , null
+ , function (testName, testResult, actual, expected) {
+ console.log("[" + testName + "]: " + (testResult ? "passed" : "FAILED"));
+ }, function (elapsed, passed, failed) {
+ testResults['Parser'] = {
+ elapsed: elapsed
+ , passed: passed
+ , failed: failed
+ };
+ });
+testUtils.runParserTests(
+ parserTests
+ , htmlparser.Parser
+ , function (test) {
+ var newTest = {};
+ for (var key in test) {
+ if (!test.hasOwnProperty(key)) {
+ continue;
+ }
+ newTest[key] = (key === 'data') ?
+ test.data.join('').split('')
+ :
+ test[key]
+ ;
}
- newTest[key] = (key === 'data') ?
- test.data.join('').split('')
- :
- test[key]
- ;
+ return newTest;
}
- return newTest;
-});
+ , function (testName, testResult, actual, expected) {
+ console.log("[" + testName + "]: " + (testResult ? "passed" : "FAILED"));
+ }, function (elapsed, passed, failed) {
+ testResults['Parser (streamed)'] = {
+ elapsed: elapsed
+ , passed: passed
+ , failed: failed
+ };
+ });
console.log('');
console.log('Test Results');
View
50 tests/html.js
@@ -1,28 +1,40 @@
-(function () {
+/***********************************************
+Copyright 2010 - 2012, Chris Winberry <chris@winberry.net>. All rights reserved.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
-function RunningInNode () {
- return(
- (typeof require) == "function"
- &&
- (typeof exports) == "object"
- &&
- (typeof module) == "object"
- &&
- (typeof __filename) == "string"
- &&
- (typeof __dirname) == "string"
- );
-}
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
-exports = exports || {};
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
+***********************************************/
+
+(function () {
-if (!RunningInNode()) {
- if (!this.Tautologistics)
+var exports;
+if (typeof(module) !== 'undefined' && typeof(module.exports) !== 'undefined') {
+ exports = module.exports;
+} else {
+ exports = {};
+ if (!this.Tautologistics) {
this.Tautologistics = {};
- if (!this.Tautologistics.NodeHtmlParser)
+ }
+ if (!this.Tautologistics.NodeHtmlParser) {
this.Tautologistics.NodeHtmlParser = {};
- if (!this.Tautologistics.NodeHtmlParser.Tests)
+ }
+ if (!this.Tautologistics.NodeHtmlParser.Tests) {
this.Tautologistics.NodeHtmlParser.Tests = [];
+ }
this.Tautologistics.NodeHtmlParser.Tests.Html = exports;
}
View
281 tests/parser.js
@@ -1,28 +1,40 @@
-(function () {
-
-function RunningInNode () {
- return(
- (typeof require) == "function"
- &&
- (typeof exports) == "object"
- &&
- (typeof module) == "object"
- &&
- (typeof __filename) == "string"
- &&
- (typeof __dirname) == "string"
- );
-}
+/***********************************************
+Copyright 2010 - 2012, Chris Winberry <chris@winberry.net>. All rights reserved.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
+***********************************************/
-exports = exports || {};
+(function () {
-if (!RunningInNode()) {
- if (!this.Tautologistics)
+var exports;
+if (typeof(module) !== 'undefined' && typeof(module.exports) !== 'undefined') {
+ exports = module.exports;
+} else {
+ exports = {};
+ if (!this.Tautologistics) {
this.Tautologistics = {};
- if (!this.Tautologistics.NodeHtmlParser)
+ }
+ if (!this.Tautologistics.NodeHtmlParser) {
this.Tautologistics.NodeHtmlParser = {};
- if (!this.Tautologistics.NodeHtmlParser.Tests)
+ }
+ if (!this.Tautologistics.NodeHtmlParser.Tests) {
this.Tautologistics.NodeHtmlParser.Tests = [];
+ }
this.Tautologistics.NodeHtmlParser.Tests.Parser = exports;
}
@@ -31,11 +43,6 @@ exports['plain text'] = {
, expected: [{ type: 'text', data: 'This is the text' }]
};
-exports['split text'] = {
- data: ['This is', ' the text']
- , expected: [{ type: 'text', data: 'This is the text' }]
-};
-
exports['simple tag'] = {
data: ['<div>']
, expected: [{ type: 'tag', name: 'div', raw: 'div' }]
@@ -51,21 +58,6 @@ exports['simple cdata'] = {
, expected: [{ type: 'cdata', data: ' content ' }]
};
-exports['split simple tag #1'] = {
- data: ['<', 'div>']
- , expected: [{ type: 'tag', name: 'div', raw: 'div' }]
-};
-
-exports['split simple tag #2'] = {
- data: ['<d', 'iv>']
- , expected: [{ type: 'tag', name: 'div', raw: 'div' }]
-};
-
-exports['split simple tag #3'] = {
- data: ['<div', '>']
- , expected: [{ type: 'tag', name: 'div', raw: 'div' }]
-};
-
exports['text before tag'] = {
data: ['xxx<div>']
, expected: [
@@ -291,22 +283,6 @@ exports['self closing tag with attribute, trailing text'] = {
]
};
-exports['self closing tag split #1'] = {
- data: ['<div/', '>']
- , expected: [
- { type: 'tag', name: 'div', raw: 'div/' },
- { type: 'tag', name: '/div', raw: null }
- ]
-};
-
-exports['self closing tag split #2'] = {
- data: ['<div', '/>']
- , expected: [
- { type: 'tag', name: 'div', raw: 'div/' },
- { type: 'tag', name: '/div', raw: null }
- ]
-};
-
exports['attribute missing close quote'] = {
data: ['<div a="1><span id="foo">xxx']
, expected: [
@@ -317,70 +293,6 @@ exports['attribute missing close quote'] = {
]
};
-exports['split attribute #1'] = {
- data: ['<div x', 'xx="yyy">']
- , expected: [
- { type: 'tag', name: 'div', raw: 'div xxx="yyy"' },
- { type: 'attr', name:'xxx', data: 'yyy'}
- ]
-};
-
-exports['split attribute #2'] = {
- data: ['<div xxx', '="yyy">']
- , expected: [
- { type: 'tag', name: 'div', raw: 'div xxx="yyy"' },
- { type: 'attr', name:'xxx', data: 'yyy'}
- ]
-};
-
-exports['split attribute #3'] = {
- data: ['<div xxx=', '"yyy">']
- , expected: [
- { type: 'tag', name: 'div', raw: 'div xxx="yyy"' },
- { type: 'attr', name:'xxx', data: 'yyy'}
- ]
-};
-
-exports['split attribute #4'] = {
- data: ['<div xxx="', 'yyy">']
- , expected: [
- { type: 'tag', name: 'div', raw: 'div xxx="yyy"' },
- { type: 'attr', name:'xxx', data: 'yyy'}
- ]
-};
-
-exports['split attribute #5'] = {
- data: ['<div xxx="yy', 'y">']
- , expected: [
- { type: 'tag', name: 'div', raw: 'div xxx="yyy"' },
- { type: 'attr', name:'xxx', data: 'yyy'}
- ]
-};
-
-exports['split attribute #6'] = {
- data: ['<div xxx="yyy', '">']
- , expected: [
- { type: 'tag', name: 'div', raw: 'div xxx="yyy"' },
- { type: 'attr', name:'xxx', data: 'yyy'}
- ]
-};
-
-exports['attribute split from tag #1'] = {
- data: ['<div ', 'xxx="yyy">']
- , expected: [
- { type: 'tag', name: 'div', raw: 'div xxx="yyy"' },
- { type: 'attr', name:'xxx', data: 'yyy'}
- ]
-};
-
-exports['attribute split from tag #2'] = {
- data: ['<div', ' xxx="yyy">']
- , expected: [
- { type: 'tag', name: 'div', raw: 'div xxx="yyy"' },
- { type: 'attr', name:'xxx', data: 'yyy'}
- ]
-};
-
exports['text before complex tag'] = {
data: ['xxx<div yyy="123">']
, expected: [
@@ -484,135 +396,6 @@ exports['brackets in attribute'] = {
]
};
-exports['split comment #1'] = {
- data: ['<','!-- comment text -->xxx']
- , expected: [
- { type: 'comment', data: ' comment text '},
- { type: 'text', data: 'xxx' }
- ]
-};
-
-exports['split comment #2'] = {
- data: ['<!','-- comment text -->xxx']
- , expected: [
- { type: 'comment', data: ' comment text '},
- { type: 'text', data: 'xxx' }
- ]
-};
-
-exports['split comment #3'] = {
- data: ['<!-','- comment text -->xxx']
- , expected: [
- { type: 'comment', data: ' comment text '},
- { type: 'text', data: 'xxx' }
- ]
-};
-
-exports['split comment #4'] = {
- data: ['<!--',' comment text -->xxx']
- , expected: [
- { type: 'comment', data: ' comment text '},
- { type: 'text', data: 'xxx' }
- ]
-};
-
-exports['split comment #5'] = {
- data: ['<!-- comment',' text -->xxx']
- , expected: [
- { type: 'comment', data: ' comment text '},
- { type: 'text', data: 'xxx' }
- ]
-};
-
-exports['split comment #6'] = {
- data: ['<!-- comment text ','-->xxx']
- , expected: [
- { type: 'comment', data: ' comment text '},
- { type: 'text', data: 'xxx' }
- ]
-};
-
-exports['split comment #7'] = {
- data: ['<!-- comment text -','->xxx']
- , expected: [
- { type: 'comment', data: ' comment text '},
- { type: 'text', data: 'xxx' }
- ]
-};
-
-exports['split comment #8'] = {
- data: ['<!-- comment text --','>xxx']
- , expected: [
- { type: 'comment', data: ' comment text '},
- { type: 'text', data: 'xxx' }
- ]
-};
-
-exports['split cdata #1'] = {
- data: ['<','![CDATA[ CData content ]]>']
- , expected: [{ type: 'cdata', data: ' CData content '}]
-};
-
-exports['split cdata #2'] = {
- data: ['<!','[CDATA[ CData content ]]>']
- , expected: [{ type: 'cdata', data: ' CData content '}]
-};
-
-exports['split cdata #3'] = {
- data: ['<![','CDATA[ CData content ]]>']
- , expected: [{ type: 'cdata', data: ' CData content '}]
-};
-
-exports['split cdata #4'] = {
- data: ['<![C','DATA[ CData content ]]>']
- , expected: [{ type: 'cdata', data: ' CData content '}]
-};
-
-exports['split cdata #5'] = {
- data: ['<![CD','ATA[ CData content ]]>']
- , expected: [{ type: 'cdata', data: ' CData content '}]
-};
-
-exports['split cdata #6'] = {
- data: ['<![CDA','TA[ CData content ]]>']
- , expected: [{ type: 'cdata', data: ' CData content '}]
-};
-
-exports['split cdata #7'] = {
- data: ['<![CDAT','A[ CData content ]]>']
- , expected: [{ type: 'cdata', data: ' CData content '}]
-};
-
-exports['split cdata #8'] = {
- data: ['<![CDATA','[ CData content ]]>']
- , expected: [{ type: 'cdata', data: ' CData content '}]
-};
-
-exports['split cdata #9'] = {
- data: ['<![CDATA[',' CData content ]]>']
- , expected: [{ type: 'cdata', data: ' CData content '}]
-};
-
-exports['split cdata #10'] = {
- data: ['<![CDATA[ CData ','content ]]>']
- , expected: [{ type: 'cdata', data: ' CData content '}]
-};
-
-exports['split cdata #11'] = {
- data: ['<![CDATA[ CData content ',']]>']
- , expected: [{ type: 'cdata', data: ' CData content '}]
-};
-
-exports['split cdata #12'] = {
- data: ['<![CDATA[ CData content ]',']>']
- , expected: [{ type: 'cdata', data: ' CData content '}]
-};
-
-exports['split cdata #13'] = {
- data: ['<![CDATA[ CData content ]]','>']
- , expected: [{ type: 'cdata', data: ' CData content '}]
-};
-
exports['unfinished simple tag #1'] = {
data: ['<div']
, expected: [{ type: 'tag', name: 'div', raw: 'div'}]
View
50 tests/rss.js
@@ -1,28 +1,40 @@
-(function () {
+/***********************************************
+Copyright 2010 - 2012, Chris Winberry <chris@winberry.net>. All rights reserved.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
-function RunningInNode () {
- return(
- (typeof require) == "function"
- &&
- (typeof exports) == "object"
- &&
- (typeof module) == "object"
- &&
- (typeof __filename) == "string"
- &&
- (typeof __dirname) == "string"
- );
-}
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
-exports = exports || {};
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
+***********************************************/
+
+(function () {
-if (!RunningInNode()) {
- if (!this.Tautologistics)
+var exports;
+if (typeof(module) !== 'undefined' && typeof(module.exports) !== 'undefined') {
+ exports = module.exports;
+} else {
+ exports = {};
+ if (!this.Tautologistics) {
this.Tautologistics = {};
- if (!this.Tautologistics.NodeHtmlParser)
+ }
+ if (!this.Tautologistics.NodeHtmlParser) {
this.Tautologistics.NodeHtmlParser = {};
- if (!this.Tautologistics.NodeHtmlParser.Tests)
+ }
+ if (!this.Tautologistics.NodeHtmlParser.Tests) {
this.Tautologistics.NodeHtmlParser.Tests = [];
+ }
this.Tautologistics.NodeHtmlParser.Tests.Rss = exports;
}
View
195 tests/testutils.js
@@ -0,0 +1,195 @@
+/***********************************************
+Copyright 2010 - 2012, Chris Winberry <chris@winberry.net>. All rights reserved.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to
+deal in the Software without restriction, including without limitation the
+rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+sell copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+IN THE SOFTWARE.
+***********************************************/
+
+(function () {
+
+var exports;
+if (typeof(module) !== 'undefined' && typeof(module.exports) !== 'undefined') {
+ exports = module.exports;
+} else {
+ exports = {};
+ if (!this.Tautologistics) {
+ this.Tautologistics = {};
+ }
+ if (!this.Tautologistics.NodeHtmlParser) {
+ this.Tautologistics.NodeHtmlParser = {};
+ }
+ if (!this.Tautologistics.NodeHtmlParser.Tests) {
+ this.Tautologistics.NodeHtmlParser.Tests = [];
+ }
+ this.Tautologistics.NodeHtmlParser.Tests.Utils = exports;
+}
+
+exports.compareObjects = function (a, b) {
+ //http://stackoverflow.com/questions/1068834/object-comparison-in-javascript
+ var p;
+
+ for (p in a) {
+ if (typeof(b[p]) == 'undefined') {
+ // console.log('Missing property: ', p);
+ return false;
+ }
+ }
+
+ for (p in b) {
+ if (typeof(a[p]) == 'undefined') {
+ // console.log('Extra property: ', p);
+ return false;
+ }
+ }
+
+ for (p in a) {
+ if (a[p]) {
+ switch(typeof(a[p])) {
+ case 'object':
+ if (!exports.compareObjects(a[p], b[p])) {
+ // console.log('Mismatched property: ', p);
+ return false;
+ }
+ break;
+ case 'function':
+ if (typeof(b[p])=='undefined' || (p != 'equals' && a[p].toString() != b[p].toString())) {
+ // console.log('Mismatched property: ', p);
+ return false;
+ }
+ break;
+ default:
+ if (a[p] != b[p]) {
+ // console.log('Mismatched property: ', p);
+ return false;
+ }
+ }
+ } else {
+ if (b[p]) {
+ // console.log('Poop: ', p);
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+exports.runBuilderTests = function (tests, parserCtor, builderCtor, permutator, testHandler, resultsHandler) {
+ var passed = 0;
+ var failed = 0;
+
+ var builderCallback = function builderCallback (error) {
+ if (error) {
+ // util.puts("Builder error: " + error);
+ }
+ };
+
+ // console.log(tests);
+
+ var startTime = Date.now();
+ for (var testName in tests) {
+ if (!tests.hasOwnProperty(testName)) {
+ continue;
+ }
+ var test = permutator ? permutator(tests[testName]) : tests[testName];
+
+ var builder = new builderCtor(builderCallback, test.options.builder);
+ var parser = new parserCtor(builder, test.options.parser);
+
+ parser.reset();
+ if (test.data.length === 1) {
+ parser.parseComplete(test.data[0]);
+ } else {
+ for (var i = 0, len = test.data.length; i < len; i++) {
+ parser.parseChunk(test.data[i]);
+ }
+ parser.done();
+ }
+ var testResult = exports.compareObjects(builder.dom, test.expected);
+
+ testHandler(testName, testResult, builder.dom, test.expected);
+ if (!testResult) {
+ failed++;
+ } else {
+ passed++;
+ }
+ }
+ var endTime = Date.now();
+
+ resultsHandler(endTime - startTime, passed, failed);
+}
+
+function TestBuilder (callback) {
+ this.cb = callback;
+ this.reset();
+}
+TestBuilder.prototype.reset = function () {
+ this.output = [];
+}
+TestBuilder.prototype.write = function (element) {
+ this.output.push(element);
+}
+TestBuilder.prototype.done = function () {
+ this.cb(null, this.output);
+}
+TestBuilder.prototype.error = function (error) {
+ this.cb(error);
+}
+
+exports.runParserTests = function (tests, parserCtor, permutator, testHandler, resultsHandler) {
+ var callback = function builderCallback (err) {
+ if (err) {
+ console.log('Builder error', err);
+ }
+ };
+ var builder = new TestBuilder(callback);
+ var parser = new parserCtor(builder);
+
+ var passed = 0;
+ var failed = 0;
+
+ var startTime = Date.now();
+ for (var testName in tests) {
+ if (!tests.hasOwnProperty(testName)) {
+ continue;
+ }
+ var test = permutator ? permutator(tests[testName]) : tests[testName];
+ parser.reset();
+ if (test.data.length === 1) {
+ parser.parseComplete(test.data[0]);
+ } else {
+ for (var i = 0, len = test.data.length; i < len; i++) {
+ parser.parseChunk(test.data[i]);
+ }
+ parser.done();
+ }
+
+ var testResult = exports.compareObjects(builder.output, test.expected);
+ testHandler(testName, testResult, builder.dom, test.expected);
+
+ if (!testResult) {
+ failed++;
+ } else {
+ passed++;
+ }
+ }
+ var endTime = Date.now();
+
+ resultsHandler(endTime - startTime, passed, failed);
+}
+
+})();

0 comments on commit 6b775db

Please sign in to comment.
Something went wrong with that request. Please try again.