• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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