1var fs = require('fs'), 2 path = require('path'), 3 parse5 = require('../index'), 4 HTML = require('../lib/common/html'); 5 6function addSlashes(str) { 7 return str 8 .replace(/\t/g, '\\t') 9 .replace(/\n/g, '\\n') 10 .replace(/\f/g, '\\f') 11 .replace(/\r/g, '\\r'); 12} 13 14function createDiffMarker(markerPosition) { 15 var marker = ''; 16 17 for (var i = 0; i < markerPosition - 1; i++) 18 marker += ' '; 19 20 return marker + '^\n'; 21} 22 23//NOTE: creates test suites for each available tree adapter. 24exports.generateTestsForEachTreeAdapter = function (moduleExports, ctor) { 25 Object.keys(parse5.TreeAdapters).forEach(function (adapterName) { 26 var tests = {}, 27 adapter = parse5.TreeAdapters[adapterName]; 28 29 ctor(tests, adapter); 30 31 Object.keys(tests).forEach(function (testName) { 32 moduleExports['Tree adapter: ' + adapterName + ' - ' + testName] = tests[testName]; 33 }); 34 }); 35}; 36 37exports.getStringDiffMsg = function (actual, expected) { 38 for (var i = 0; i < expected.length; i++) { 39 if (actual[i] !== expected[i]) { 40 var diffMsg = '\nString differ at index ' + i + '\n'; 41 42 var expectedStr = 'Expected: ' + addSlashes(expected.substring(i - 100, i + 1)), 43 expectedDiffMarker = createDiffMarker(expectedStr.length); 44 45 diffMsg += expectedStr + addSlashes(expected.substring(i + 1, i + 20)) + '\n' + expectedDiffMarker; 46 47 var actualStr = 'Actual: ' + addSlashes(actual.substring(i - 100, i + 1)), 48 actualDiffMarker = createDiffMarker(actualStr.length); 49 50 diffMsg += actualStr + addSlashes(actual.substring(i + 1, i + 20)) + '\n' + actualDiffMarker; 51 52 return diffMsg; 53 } 54 } 55 56 return ''; 57}; 58 59exports.removeNewLines = function (str) { 60 return str 61 .replace(/\r/g, '') 62 .replace(/\n/g, ''); 63}; 64 65function normalizeNewLine(str) { 66 return str.replace(/\r\n/g, '\n'); 67} 68 69exports.loadSerializationTestData = function (dataDirPath) { 70 var testSetFileDirs = fs.readdirSync(dataDirPath), 71 tests = []; 72 73 testSetFileDirs.forEach(function (dirName) { 74 var srcFilePath = path.join(dataDirPath, dirName, 'src.html'), 75 expectedFilePath = path.join(dataDirPath, dirName, 'expected.html'), 76 src = fs.readFileSync(srcFilePath).toString(), 77 expected = fs.readFileSync(expectedFilePath).toString(); 78 79 tests.push({ 80 name: dirName, 81 src: normalizeNewLine(src), 82 expected: normalizeNewLine(expected) 83 }); 84 }); 85 86 return tests; 87}; 88 89exports.loadTreeConstructionTestData = function (dataDirs, treeAdapter) { 90 var testIdx = 0, 91 tests = []; 92 93 dataDirs.forEach(function (dataDirPath) { 94 var testSetFileNames = fs.readdirSync(dataDirPath), 95 dirName = path.basename(dataDirPath); 96 97 testSetFileNames.forEach(function (fileName) { 98 var filePath = path.join(dataDirPath, fileName), 99 testSet = fs.readFileSync(filePath).toString(), 100 setName = fileName.replace('.dat', ''), 101 testDescrs = [], 102 curDirective = '', 103 curDescr = null; 104 105 testSet.split(/\r?\n/).forEach(function (line) { 106 if (line === '#data') { 107 curDescr = {}; 108 testDescrs.push(curDescr); 109 } 110 111 if (line[0] === '#') { 112 curDirective = line; 113 curDescr[curDirective] = []; 114 } 115 116 else 117 curDescr[curDirective].push(line); 118 }); 119 120 testDescrs.forEach(function (descr) { 121 var fragmentContextTagName = descr['#document-fragment'] && descr['#document-fragment'].join(''); 122 123 tests.push({ 124 idx: ++testIdx, 125 setName: setName, 126 dirName: dirName, 127 input: descr['#data'].join('\r\n'), 128 expected: descr['#document'].join('\n'), 129 expectedErrors: descr['#errors'], 130 disableEntitiesDecoding: !!descr['#disable-html-entities-decoding'], 131 fragmentContext: fragmentContextTagName && 132 treeAdapter.createElement(fragmentContextTagName, HTML.NAMESPACES.HTML, []) 133 }); 134 }); 135 }); 136 }); 137 138 return tests; 139}; 140 141exports.serializeToTestDataFormat = function (rootNode, treeAdapter) { 142 function getSerializedTreeIndent(indent) { 143 var str = '|'; 144 145 for (var i = 0; i < indent + 1; i++) 146 str += ' '; 147 148 return str; 149 } 150 151 function getElementSerializedNamespaceURI(element) { 152 switch (treeAdapter.getNamespaceURI(element)) { 153 case HTML.NAMESPACES.SVG: 154 return 'svg '; 155 case HTML.NAMESPACES.MATHML: 156 return 'math '; 157 default : 158 return ''; 159 } 160 } 161 162 function serializeNodeList(nodes, indent) { 163 var str = ''; 164 165 nodes.forEach(function (node) { 166 str += getSerializedTreeIndent(indent); 167 168 if (treeAdapter.isCommentNode(node)) 169 str += '<!-- ' + treeAdapter.getCommentNodeContent(node) + ' -->\n'; 170 171 else if (treeAdapter.isTextNode(node)) 172 str += '"' + treeAdapter.getTextNodeContent(node) + '"\n'; 173 174 else if (treeAdapter.isDocumentTypeNode(node)) { 175 var parts = [], 176 publicId = treeAdapter.getDocumentTypeNodePublicId(node), 177 systemId = treeAdapter.getDocumentTypeNodeSystemId(node); 178 179 str += '<!DOCTYPE'; 180 181 parts.push(treeAdapter.getDocumentTypeNodeName(node) || ''); 182 183 if (publicId !== null || systemId !== null) { 184 parts.push('"' + (publicId || '') + '"'); 185 parts.push('"' + (systemId || '') + '"'); 186 } 187 188 parts.forEach(function (part) { 189 str += ' ' + part; 190 }); 191 192 str += '>\n'; 193 } 194 195 else { 196 var tn = treeAdapter.getTagName(node); 197 198 str += '<' + getElementSerializedNamespaceURI(node) + tn + '>\n'; 199 200 var childrenIndent = indent + 2, 201 serializedAttrs = []; 202 203 treeAdapter.getAttrList(node).forEach(function (attr) { 204 var attrStr = getSerializedTreeIndent(childrenIndent); 205 206 if (attr.prefix) 207 attrStr += attr.prefix + ' '; 208 209 attrStr += attr.name + '="' + attr.value + '"\n'; 210 211 serializedAttrs.push(attrStr); 212 }); 213 214 str += serializedAttrs.sort().join(''); 215 216 if (tn === HTML.TAG_NAMES.TEMPLATE && treeAdapter.getNamespaceURI(node) === HTML.NAMESPACES.HTML) { 217 str += getSerializedTreeIndent(childrenIndent) + 'content\n'; 218 childrenIndent += 2; 219 node = treeAdapter.getChildNodes(node)[0]; 220 } 221 222 str += serializeNodeList(treeAdapter.getChildNodes(node), childrenIndent); 223 } 224 }); 225 226 return str; 227 } 228 229 return serializeNodeList(treeAdapter.getChildNodes(rootNode), 0); 230}; 231 232exports.prettyPrintParserAssertionArgs = function (actual, expected) { 233 var msg = '\nExpected:\n'; 234 msg += '-----------------\n'; 235 msg += expected + '\n'; 236 msg += '\nActual:\n'; 237 msg += '-----------------\n'; 238 msg += actual + '\n'; 239 240 return msg; 241}; 242