1var assert = require('assert'),
2    path = require('path'),
3    HTML = require('../../lib/common/html'),
4    parse5 = require('../../index'),
5    Parser = parse5.Parser,
6    Serializer = parse5.Serializer,
7    TestUtils = require('../test_utils');
8
9
10TestUtils.generateTestsForEachTreeAdapter(module.exports, function (_test, treeAdapter) {
11    function getFullTestName(test) {
12        return ['Parser(', test.dirName, ') - ', test.idx, '.', test.setName, ' - ', test.input].join('');
13    }
14
15    function getLocationFullTestName(test) {
16        return ['Parser(Location info) - ', test.name].join('');
17    }
18
19    function walkTree(document, handler) {
20        for (var stack = treeAdapter.getChildNodes(document).slice(); stack.length;) {
21            var node = stack.shift(),
22                children = treeAdapter.getChildNodes(node);
23
24            handler(node);
25
26            if (children && children.length)
27                stack = children.concat(stack);
28        }
29    }
30
31    //Here we go..
32    TestUtils.loadTreeConstructionTestData([
33        path.join(__dirname, '../data/tree_construction'),
34        path.join(__dirname, '../data/tree_construction_regression'),
35        path.join(__dirname, '../data/tree_construction_options')
36    ], treeAdapter).forEach(function (test) {
37        _test[getFullTestName(test)] = function () {
38            var parser = new Parser(treeAdapter, {
39                    decodeHtmlEntities: !test.disableEntitiesDecoding
40                }),
41                result = test.fragmentContext ?
42                         parser.parseFragment(test.input, test.fragmentContext) :
43                         parser.parse(test.input),
44                actual = TestUtils.serializeToTestDataFormat(result, treeAdapter),
45                msg = TestUtils.prettyPrintParserAssertionArgs(actual, test.expected);
46
47            assert.strictEqual(actual, test.expected, msg);
48        };
49    });
50
51
52    //Location info tests
53    TestUtils.loadSerializationTestData(path.join(__dirname, '../data/serialization')).forEach(function (test) {
54        //NOTE: the idea of this test is the following: we parse document with the location info.
55        //Then for each node in the tree we run serializer and compare results with the substring
56        //obtained via location info from the expected serialization results.
57        _test[getLocationFullTestName(test)] = function () {
58            var parser = new Parser(treeAdapter, {
59                    locationInfo: true,
60                    decodeHtmlEntities: false
61                }),
62                serializer = new Serializer(treeAdapter, {
63                    encodeHtmlEntities: false
64                }),
65                html = test.expected,
66                document = parser.parse(html);
67
68            walkTree(document, function (node) {
69                if (node.__location !== null) {
70                    var fragment = treeAdapter.createDocumentFragment();
71
72                    treeAdapter.appendChild(fragment, node);
73
74                    var expected = serializer.serialize(fragment),
75                        actual = html.substring(node.__location.start, node.__location.end);
76
77                    expected = TestUtils.removeNewLines(expected);
78                    actual = TestUtils.removeNewLines(actual);
79
80                    //NOTE: use ok assertion, so output will not be polluted by the whole content of the strings
81                    assert.ok(actual === expected, TestUtils.getStringDiffMsg(actual, expected));
82
83                    if (node.__location.startTag) {
84                        //NOTE: Based on the idea that the serialized fragment starts with the startTag
85                        var length = node.__location.startTag.end - node.__location.startTag.start,
86                            expectedStartTag = serializer.serialize(fragment).substring(0, length),
87                            actualStartTag = html.substring(node.__location.startTag.start, node.__location.startTag.end);
88
89                        expectedStartTag = TestUtils.removeNewLines(expectedStartTag);
90                        actualStartTag = TestUtils.removeNewLines(actualStartTag);
91
92                        assert.ok(expectedStartTag === actualStartTag, TestUtils.getStringDiffMsg(actualStartTag, expectedStartTag));
93                    }
94
95                    if (node.__location.endTag) {
96                        //NOTE: Based on the idea that the serialized fragment ends with the endTag
97                        var length = node.__location.endTag.end - node.__location.endTag.start,
98                            expectedEndTag = serializer.serialize(fragment).slice(-length),
99                            actualEndTag = html.substring(node.__location.endTag.start, node.__location.endTag.end);
100
101                        expectedEndTag = TestUtils.removeNewLines(expectedEndTag);
102                        actualEndTag = TestUtils.removeNewLines(actualEndTag);
103
104                        assert.ok(expectedEndTag === actualEndTag, TestUtils.getStringDiffMsg(actualEndTag, expectedEndTag));
105                    }
106                }
107            });
108        };
109    });
110
111    exports['Regression - location info for the implicitly generated <body>, <html> and <head> (GH-44)'] = function () {
112        var html = '</head><div class="test"></div></body></html>',
113            parser = new Parser(treeAdapter, {
114                locationInfo: true,
115                decodeHtmlEntities: false
116            }),
117            document = parser.parse(html);
118
119        //NOTE: location info for all implicitly generated elements should be null
120        walkTree(document, function (node) {
121            if (treeAdapter.getTagName(node) !== HTML.TAG_NAMES.DIV)
122                assert.strictEqual(node.__location, null);
123        });
124    };
125});
126
127
128exports['Regression - HTML5 Legacy Doctype Misparsed with htmlparser2 tree adapter (GH-45)'] = function () {
129    var html = '<!DOCTYPE html SYSTEM "about:legacy-compat"><html><head></head><body>Hi there!</body></html>',
130        parser = new Parser(parse5.TreeAdapters.htmlparser2),
131        document = parser.parse(html);
132
133    assert.strictEqual(document.childNodes[0].data, '!DOCTYPE html SYSTEM "about:legacy-compat"');
134};
135
136
137