1const fs = require('fs'); 2const path = require('path'); 3const assert = require('assert'); 4const serializeToDatFileFormat = require('./serialize-to-dat-file-format'); 5const { generateTestsForEachTreeAdapter } = require('./common'); 6const parseDatFile = require('../../test/utils/parse-dat-file'); 7 8function loadTreeConstructionTestData(dataDirs, treeAdapter) { 9 const tests = []; 10 11 dataDirs.forEach(dataDirPath => { 12 const testSetFileNames = fs.readdirSync(dataDirPath); 13 const dirName = path.basename(dataDirPath); 14 15 testSetFileNames.forEach(fileName => { 16 if (path.extname(fileName) !== '.dat') { 17 return; 18 } 19 20 const filePath = path.join(dataDirPath, fileName); 21 const testSet = fs.readFileSync(filePath, 'utf-8'); 22 const setName = fileName.replace('.dat', ''); 23 24 parseDatFile(testSet, treeAdapter).forEach(test => { 25 tests.push( 26 Object.assign(test, { 27 idx: tests.length, 28 setName: setName, 29 dirName: dirName 30 }) 31 ); 32 }); 33 }); 34 }); 35 36 return tests; 37} 38 39function prettyPrintParserAssertionArgs(actual, expected, chunks) { 40 let msg = '\nExpected:\n'; 41 42 msg += '-----------------\n'; 43 msg += expected + '\n'; 44 msg += '\nActual:\n'; 45 msg += '-----------------\n'; 46 msg += actual + '\n'; 47 48 if (chunks) { 49 msg += 'Chunks:\n'; 50 msg += JSON.stringify(chunks); 51 } 52 53 return msg; 54} 55 56function createParsingTest(test, treeAdapter, parse, { withoutErrors }) { 57 return async () => { 58 const errs = []; 59 60 const opts = { 61 scriptingEnabled: test.scriptingEnabled, 62 treeAdapter: treeAdapter, 63 64 onParseError: err => { 65 let errStr = `(${err.startLine}:${err.startCol}`; 66 67 // NOTE: use ranges for token errors 68 if (err.startLine !== err.endLine || err.startCol !== err.endCol) { 69 errStr += `-${err.endLine}:${err.endCol}`; 70 } 71 72 errStr += `) ${err.code}`; 73 74 errs.push(errStr); 75 } 76 }; 77 78 const { node, chunks } = await parse(test, opts); 79 const actual = serializeToDatFileFormat(node, opts.treeAdapter); 80 const msg = prettyPrintParserAssertionArgs(actual, test.expected, chunks); 81 82 assert.strictEqual(actual, test.expected, msg); 83 84 if (!withoutErrors) { 85 assert.deepEqual(errs.sort(), test.expectedErrors.sort()); 86 } 87 }; 88} 89 90module.exports = function generateParsingTests( 91 moduleExports, 92 prefix, 93 { 94 skipFragments, 95 withoutErrors, 96 testSuite = [ 97 path.join(__dirname, '../data/html5lib-tests/tree-construction'), 98 path.join(__dirname, '../data/tree-construction-regression') 99 ] 100 }, 101 parse 102) { 103 generateTestsForEachTreeAdapter(moduleExports, (_test, treeAdapter) => { 104 loadTreeConstructionTestData(testSuite, treeAdapter).forEach(test => { 105 if (!(test.fragmentContext && skipFragments)) { 106 const testName = `${prefix}(${test.dirName}) - ${test.idx}.${test.setName} - \`${test.input}\` (line ${ 107 test.lineNum 108 })`; 109 110 _test[testName] = createParsingTest(test, treeAdapter, parse, { withoutErrors }); 111 } 112 }); 113 }); 114}; 115 116module.exports.loadTreeConstructionTestData = loadTreeConstructionTestData; 117