summaryrefslogtreecommitdiffstats
path: root/LayoutTests/fast/dom/Node/fragment-mutation.html
blob: 037e17bf5002f84691f180760664fc41630bc3ae (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<html>
<head>
<title>Fragment Mutation Tests</title>
<script>

if (window.layoutTestController)
    layoutTestController.dumpAsText();

var log = [];

function logResult(description, outcome)
{
    log.push({ description: description, outcome: outcome});
}

function printLog(methodName)
{
    var entries = log.map(function(entry) {
        return "<li>" + entry.description + ": " + entry.outcome;
    });
    document.body.appendChild(document.createElement("p")).innerHTML = "This test creates a fragment containing three elements: \"B\", \"U\", and \"P\", " +
        "  attempts to " + methodName + " this fragment and studies effects of mutation events on the fragment.";
    document.body.appendChild(document.createElement("ul")).innerHTML = entries.join("\n");
    document.body.appendChild(document.createElement("br"));
    log = [];
}

function produceNodeNameString(nodes)
{
    var node = nodes.firstChild;
    var result = "";
    while(node) {
        result += node.nodeName;
        node = node.nextSibling;
    }
    return result;
}

function expectException(code)
{
    return function(stash, exception) {
        if (!exception)
            return "FAIL, expected exception with code " + code + ". The resulting fragment was: \"" + produceNodeNameString(stash) + "\".";

        if (code == exception.code)
            return "PASS";
        return "FAIL, expected exception code: " + code + ", was: " + exception + ".";
    }
}

function expectNodes(nodes)
{
    return function(stash, exception) {
        if (exception)
            return "FAIL, unexpected exception thrown: " + exception;
        var result = produceNodeNameString(stash);
        if (nodes == result)
            return "PASS";
        return "FAIL, expected \"" + nodes + "\", was \"" + result + "\".";
    };
}

function testFragment(method, description, mutationHandler, expectation, nonStop)
{
    var once = 0;
    var logged = 0;
    var frag = document.createDocumentFragment();
    var stash = document.body.appendChild(document.createElement("div"));
        frag.appendChild(document.createElement("b"));
        frag.appendChild(document.createElement("u"));
        frag.appendChild(document.createElement("p"));
        frag.addEventListener("DOMSubtreeModified", function(evt)
        {
            if (!nonStop && once++)
               return;

            try {
                mutationHandler(evt, frag, stash);
            }
            catch(e) {
                logResult(description, expectation(stash, e));
                logged++;
            }
        }, false);

    try {
        method(stash, frag);
    }
    catch(e) {
        logResult(description, expectation(stash, e));
        logged++;
    }
    if (!logged)
        logResult(description, expectation(stash));
    document.body.removeChild(stash);
}

function appendChildMethod(object, subject)
{
    object.appendChild(subject);
}

function insertBeforeMethod(object, subject)
{
    object.insertBefore(subject, object.firstChild);
}

function runTest(methodName, method)
{
    var missing = document.body.appendChild(document.createElement("em"));
    testFragment(method, "Inserting an element in front of the next item in fragment should not affect the result", function(evt, frag)
    {
        frag.insertBefore(missing, frag.firstChild);
    }, expectNodes("BUP"));

    testFragment(method, "Removing next item should not abort iteration", function(evt, frag)
    {
        frag.removeChild(frag.firstChild);
    }, expectNodes("BUP"));

    var extra = document.body.appendChild(document.createElement("em"));
    testFragment(method, "Appending an element at the end of the fragment should not affect the result", function(evt, frag)
    {
        frag.appendChild(extra);
    }, expectNodes("BUP"));

    testFragment(method, "Continually re-appending removed element to the fragment should eventually throw NOT_FOUND_ERR", function(evt, frag, stash)
    {
        stash.insertBefore(frag.lastChild, stash.firstChild);
    }, expectException(8), true);

    testFragment(method, "Moving next item to become previous sibling of the re-parentee should not result in stack exhaustion", function(evt, frag, stash)
    {
        document.body.insertBefore(frag.firstChild, stash);
    }, expectNodes("BUP"));
    printLog(methodName);
}
function runTests()
{
    runTest("appendChild", appendChildMethod);
    runTest("insertBefore", insertBeforeMethod);
}

</script>
</head>
<body onload="runTests()">
</body>
</html>