diff --git a/tests/test-runner.js b/tests/test-runner.js index 0b1cdd4..857f385 100644 --- a/tests/test-runner.js +++ b/tests/test-runner.js @@ -1,448 +1,101 @@ -var passCount = 0; -var failCount = 0; -var testCount = 0; +var assert = chai.assert; -$(function() -{ - // First, wireup! - $('.results').on('click', 'td.rvl', function() - { - var tr = $(this).closest('tr'); - if (tr.hasClass('collapsed')) - { - $('.revealer', tr).hide(); - $('.hidden', tr).show(); - $(this).html("-"); - } - else - { - $('.revealer', tr).show(); - $('.hidden', tr).hide(); - $(this).html("+"); - } - tr.toggleClass('collapsed expanded'); - }); - $('.expand-all').click(function() - { - var $testGroup = $(this).closest('.test-group'); - $('.collapsed .rvl', $testGroup).click(); - }); - - $('.collapse-all').click(function() - { - var $testGroup = $(this).closest('.test-group'); - $('.expanded .rvl', $testGroup).click(); - }); - - function asyncDone() - { - // Finally, show the overall status. - if (failCount == 0) - $('#status').addClass('status-pass').html("All " + passCount + " test" + (passCount == 1 ? "" : "s") + " passed"); - else - $('#status').addClass('status-fail').html("" + failCount + " test" + (failCount == 1 ? "" : "s") + " failed; " + passCount + " passed"); +// Generates all tests from CORE_PARSER_TESTS in test-cases.js +describe('Core Parser Tests', function() { + function generateTest(test) { + (test.disabled ? it.skip : it)(test.description, function() { + var actual = new Papa.Parser(test.config).parse(test.input); + assert.deepEqual(JSON.stringify(actual.errors), JSON.stringify(test.expected.errors)); + assert.deepEqual(actual.data, test.expected.data); + }); } - // Next, run tests and render results! - runCoreParserTests(); - runParseTests(asyncDone); - runUnparseTests(); - runCustomTests(asyncDone); - + for (var i = 0; i < CORE_PARSER_TESTS.length; i++) { + generateTest(CORE_PARSER_TESTS[i]); + } }); -// Executes all tests in CORE_PARSER_TESTS from test-cases.js -// and renders results in the table. -function runCoreParserTests() -{ - for (var i = 0; i < CORE_PARSER_TESTS.length; i++) - { - var test = CORE_PARSER_TESTS[i]; - var passed = runTest(test); - if (passed) - passCount++; - else - failCount++; - } - - function runTest(test) - { - var actual = new Papa.Parser(test.config).parse(test.input); - var results = compare(actual.data, actual.errors, test.expected); - displayResults('#tests-for-core-parser', test, actual, results); - return results.data.passed && results.errors.passed +// Generates all tests from PARSE_TESTS in test-cases.js +describe('Parse Tests', function() { + function generateTest(test) { + (test.disabled ? it.skip : it)(test.description, function() { + var actual = Papa.parse(test.input, test.config); + assert.deepEqual(JSON.stringify(actual.errors), JSON.stringify(test.expected.errors)); + assert.deepEqual(actual.data, test.expected.data); + }); } -} - -// Executes all tests in PARSE_TESTS from test-cases.js -// and renders results in the table. -function runParseTests(asyncDone) -{ - for (var i = 0; i < PARSE_TESTS.length; i++) - { - var test = PARSE_TESTS[i]; - var passed = runTest(test); - if (passed) - passCount++; - else - failCount++; + for (var i = 0; i < PARSE_TESTS.length; i++) { + generateTest(PARSE_TESTS[i]); } +}); - var asyncRemaining = 0; - - PARSE_ASYNC_TESTS.forEach(function(test) - { - if (test.disabled) - return; - asyncRemaining++; - var config = test.config; - config.complete = function(actual) - { - var results = compare(actual.data, actual.errors, test.expected); - - displayResults("#tests-for-parse", test, actual, results); - - if (results.data.passed && results.errors.passed) { - passCount++; - } else { - failCount++; - } - if (--asyncRemaining === 0) { - asyncDone(); - } - }; - - config.error = function(err) - { - failCount++; - displayResults("#tests-for-parse", test, {data:[],errors:err}, test.expected); - if (--asyncRemaining === 0) { - asyncDone(); - } - }; - - Papa.parse(test.input, config); - }); - - - function runTest(test) - { - var actual = Papa.parse(test.input, test.config); - var results = compare(actual.data, actual.errors, test.expected); - displayResults('#tests-for-parse', test, actual, results); - return results.data.passed && results.errors.passed - } -} - - - - - -function displayResults(tableId, test, actual, results) -{ - var testId = testCount++; - - var testDescription = (test.description || ""); - if (testDescription.length > 0) - testDescription += '
'; - if (test.notes) - testDescription += '' + test.notes + ''; - - var tr = '' - + '+' - + '' + testDescription + '' - + passOrFailTd(results.data) - + passOrFailTd(results.errors) - + '
condensed
' - + '
condensed
' - + '
condensed
' - + '
condensed
' - + ''; - - $(tableId+' .results').append(tr); - - if (!results.data.passed || !results.errors.passed) - $('#test-'+testId+' td.rvl').click(); - -} - - -function compare(actualData, actualErrors, expected) -{ - var data = compareData(actualData, expected.data); - var errors = compareErrors(actualErrors, expected.errors); - - return { - data: data, - errors: errors - }; - - - function compareData(actual, expected) - { - var passed = true; - - if (actual.length != expected.length) - passed = false; - else - { - // The order is important, so we go through manually before using stringify to check everything else - for (var row = 0; row < expected.length; row++) - { - if (actual[row].length != expected[row].length) - { - passed = false; - break; - } - for (var col = 0; col < expected[row].length; col++) - { - var expectedVal = expected[row][col]; - var actualVal = actual[row][col]; +// Generates all tests from PARSE_ASYNC_TESTS in test-cases.js +describe('Parse Async Tests', function() { + function generateTest(test) { + (test.disabled ? it.skip : it)(test.description, function(done) { + var config = test.config; - if (actualVal !== expectedVal) - { - passed = false; - break; - } - } - } - } + config.complete = function(actual) { + assert.deepEqual(JSON.stringify(actual.errors), JSON.stringify(test.expected.errors)); + assert.deepEqual(actual.data, test.expected.data); + done(); + }; - if (passed) // final check will catch any other differences - passed = JSON.stringify(actual) == JSON.stringify(expected); + config.error = function(err) { + throw err; + }; - // We pass back an object right now, even though it only contains - // one value, because we might add details to the test results later - // (same with compareErrors below) - return { - passed: passed - }; + Papa.parse(test.input, config); + }); } - - function compareErrors(actual, expected) - { - var passed = JSON.stringify(actual) == JSON.stringify(expected); - - return { - passed: passed - }; + for (var i = 0; i < PARSE_ASYNC_TESTS.length; i++) { + generateTest(PARSE_ASYNC_TESTS[i]); } -} - - - - +}); -// Executes all tests in UNPARSE_TESTS from test-cases.js -// and renders results in the table. -function runUnparseTests() -{ - for (var i = 0; i < UNPARSE_TESTS.length; i++) - { - var test = UNPARSE_TESTS[i]; - var passed = runTest(test); - if (passed) - passCount++; - else - failCount++; - } - function runTest(test) - { - var actual; +// Generates all tests from UNPARSE_TESTS in test-cases.js +describe('Unparse Tests', function() { + function generateTest(test) { + (test.disabled ? it.skip : it)(test.description, function() { + var actual; - try - { - actual = Papa.unparse(test.input, test.config); - } - catch (e) - { - if (e instanceof Error) { - throw e; + try { + actual = Papa.unparse(test.input, test.config); + } catch (e) { + if (e instanceof Error) { + throw e; + } + actual = e; } - actual = e; - } - - var testId = testCount++; - var results = compare(actual, test.expected); - - var testDescription = (test.description || ""); - if (testDescription.length > 0) - testDescription += '
'; - if (test.notes) - testDescription += '' + test.notes + ''; - - var tr = '' - + '+' - + '' + testDescription + '' - + passOrFailTd(results) - + '
condensed
' - + '
condensed
' - + '
condensed
' - + '
condensed
' - + ''; - - $('#tests-for-unparse .results').append(tr); - - if (!results.passed) - $('#test-' + testId + ' td.rvl').click(); - - return results.passed; - } - - function compare(actual, expected) - { - return { - passed: actual === expected - }; - } -} - - - - -// Executes all tests in CUSTOM_TESTS from test-cases.js -// and renders results in the table. -function runCustomTests(asyncDone) -{ - var asyncRemaining = 0; - for (var i = 0; i < CUSTOM_TESTS.length; i++) - { - runTest(CUSTOM_TESTS[i]); + assert.strictEqual(actual, test.expected); + }); } - function runTest(test) - { - if (test.disabled) - return; - asyncRemaining++; - try - { - displayAsyncTest(test); - } - catch (e) - { - displayResults(test, e); - } + for (var i = 0; i < UNPARSE_TESTS.length; i++) { + generateTest(UNPARSE_TESTS[i]); } +}); - function displayAsyncTest(test) - { - var testId = testCount++; - test.testId = testId; - - var testDescription = (test.description || ""); - if (testDescription.length > 0) - testDescription += '
'; - if (test.notes) - testDescription += '' + test.notes + ''; - - var tr = '' - + '+' - + '' + testDescription + '' - + 'pending' - + '
condensed
' - + '
condensed
' - + ''; - - $('#custom-tests .results').append(tr); - test.run(function(actual) - { - displayAsyncResults(test, actual); +// Generates all tests from CUSTOM_TESTS in test-cases.js +describe('Custom Tests', function() { + function generateTest(test) { + (test.disabled ? it.skip : it)(test.description, function(done) { + test.run(function (actual) { + assert.deepEqual(JSON.stringify(actual), JSON.stringify(test.expected)); + done(); + }); }); - - setTimeout(function() - { - if (test.complete) return; - displayAsyncResults(test, '(incomplete)'); - }, 2000); } - function displayAsyncResults(test, actual) - { - var testId = test.testId; - if (test.complete) - { - asyncRemaining++; - actual = '(multiple results from test)'; - } - test.complete = true; - var results = compare(actual, test.expected); - - var tr = $('#test-'+testId); - tr.find('.actual').text(actual); - - var status = $(passOrFailTd(results)); - var oldStatus = tr.find('.status'); - oldStatus.attr('class', status.attr('class')); - oldStatus.text(status.text()); - - if (!results.passed) - $('#test-' + testId + ' td.rvl').click(); - - if (results.passed) - passCount++; - else - failCount++; - - if (--asyncRemaining === 0) - asyncDone(); - } - - - function compare(actual, expected) - { - return { - passed: JSON.stringify(actual) === JSON.stringify(expected) - }; + for (var i = 0; i < CUSTOM_TESTS.length; i++) { + generateTest(CUSTOM_TESTS[i]); } -} - - - - - - - - -// Makes a TD tag with OK or FAIL depending on test result -function passOrFailTd(result) -{ - if (result.passed) - return 'OK'; - else - return 'FAIL'; -} - - -// Reveals some hidden, whitespace, or invisible characters -function revealChars(txt) -{ - if (typeof txt != 'string') - return '(file)'; - - // Make spaces and tabs more obvious when glancing - txt = txt.replace(/( |\t)/ig, '$1'); - txt = txt.replace(/(\r\n|\n\r|\r|\n)/ig, '$1$1'); - - // Make UNIT_SEP and RECORD_SEP characters visible - txt = txt.replace(/(\u001e|\u001f)/ig, '$1$1'); - - // Now make the whitespace and invisible characters - // within the spans actually appear on the page - txt = txt.replace(/">\r\n<\/span>/ig, '">\\r\\n'); - txt = txt.replace(/">\n\r<\/span>/ig, '">\\n\\r'); - txt = txt.replace(/">\r<\/span>/ig, '">\\r'); - txt = txt.replace(/">\n<\/span>/ig, '">\\n'); - txt = txt.replace(/">\u001e<\/span>/ig, '">\\u001e'); - txt = txt.replace(/">\u001f<\/span>/ig, '">\\u001f'); - - return txt; -} +}); diff --git a/tests/tests.css b/tests/tests.css deleted file mode 100644 index 1c59cab..0000000 --- a/tests/tests.css +++ /dev/null @@ -1,173 +0,0 @@ -/* Eric Meyer's Reset CSS v2.0 */ -html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,embed,figure,figcaption,footer,header,hgroup,menu,nav,output,ruby,section,summary,time,mark,audio,video{border:0;font-size:100%;font:inherit;vertical-align:baseline;margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}body{line-height:1}ol,ul{list-style:none}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:none}table{border-collapse:collapse;border-spacing:0} - -body { - background: #F0F0F0; - font: 14px 'Helvetica Neue', sans-serif; - color: #333; - padding: 30px 15px; -} - -a { - color: rgb(0, 142, 236); -} - -a:hover { - color: rgb(82, 186, 255); -} - -b { - font-weight: bold; -} - -i { - font-style: italic; -} - -h1 { - text-align: center; - font-weight: bold; - font-size: 62px; - margin-bottom: 30px; -} - -h2 { - text-align: center; - font-weight: bold; - font-size: 26px; - margin-bottom: 20px; -} - -.status-pass, -.status-fail { - padding: 10px; - margin-bottom: 30px; - color: #FFF; - text-align: center; - text-transform: uppercase; - font-size: 18px; - letter-spacing: 1px; - font-weight: 100; -} - -.status-pass { - background: rgb(3, 168, 3); -} - -.status-fail { - background: #BB0000; -} - -.test-group { - margin-bottom: 50px; -} - -table { - width: 100%; - border-collapse: collapse; - margin-top: 5px; -} - -table th, -table td { - padding: 5px; - border: 1px solid #BBB; -} - -table th { - color: #000; - background: #DDD; - font-weight: bold; - padding: 10px 5px; - text-transform: uppercase; -} - -table td { - background: #FFF; - color: #555; - font-size: 14px; -} - -td.status { - text-transform: uppercase; - font-weight: 300; - vertical-align: middle; - text-align: center; - width: 80px; -} - -td.ok { - background: rgb(204, 250, 144); -} - -td.fail { - background: rgb(255, 192, 192); -} - -td.pending { - background: rgb(255, 255, 150); -} - -td.rvl { - background: #444; - color: #999; - vertical-align: middle; - text-align: center; - cursor: pointer; - width: 20px; -} - -td.rvl:hover { - color: #FFF; -} - -tr.collapsed td.revealable { - background: #ECECEC; - vertical-align: middle; - text-align: center; - font-family: 'Helvetica Neue', sans-serif; - text-transform: lowercase; - color: #AAA; -} - -tr.expanded .revealer { - font-family: 'Helvetica Neue', sans-serif; - text-transform: lowercase; - font-size: 10px; - background: #FFF; - position: absolute; - display: block; - padding: 3px; - top: -5px; - right: -5px; -} - -td .container { - position: relative; -} - -.notes { - color: #888; - font-size: 12px; -} - -.pre { - font-family: Menlo, Monaco, monospace; - white-space: pre-wrap; -} - -td.pre { - font-size: 12px; -} - -.hidden { - display: none; -} - -.special-char { - color: #78B7E7; -} - -.whitespace-char { - background: #D5FCFA; -} diff --git a/tests/tests.html b/tests/tests.html index 60d2342..049ef26 100644 --- a/tests/tests.html +++ b/tests/tests.html @@ -1,113 +1,25 @@ - Papa Parse Tests - + + + + + + -

Papa Parse Tests

- -
- - -
-

Core Parser Tests

- - Expand all - · - Collapse all -
- - - - - - - - - - - -
Test CaseDataErrorsConfigInputExpectedActual
-
- - - -
-

Papa.parse() Wrapper Tests

- - Expand all - · - Collapse all -
- - - - - - - - - - - -
Test CaseDataErrorsConfigInputExpectedActual
-
- - - - - - -
-

Papa.unparse() Tests

- - Expand all - · - Collapse all -
- - - - - - - - - - -
Test CaseDataConfigInputExpectedActual
-
- - - - - -
-

Miscellaneous Tests

- - Expand all - · - Collapse all -
- - - - - - - - -
Test CaseDataExpectedActual
-
- - - +
+