public void MutationObserverBothDirectAndSubtree() { var document = Html(""); var div = document.CreateElement("div"); var child = div.AppendChild(document.CreateElement("div")); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(div, childList: true, subtree: true); observer.Connect(child, childList: true); var a = document.CreateTextNode("a"); var b = document.CreateTextNode("b"); child.AppendChild(a); div.AppendChild(b); var records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 2); AssertRecord(records[0], new TestMutationRecord { Type = "childList", Target = child, Added = ToNodeList(a) }); AssertRecord(records[1], new TestMutationRecord { Type = "childList", Target = div, Added = ToNodeList(b), PreviousSibling = child }); }
public void MutationObserverCharacterdataCallback() { var document = Html(""); var div = document.CreateElement("div"); var child = div.AppendChild(document.CreateTextNode("text")); var i = 0; var observer = new MutationObserver((records, obs) => { Assert.LessOrEqual(++i, 2); Assert.AreEqual(1, records.Count()); AssertRecord(records[0], new TestMutationRecord { Type = "characterData", Target = child }); // The transient observers are removed before the callback is called. child.TextContent += " again"; records = obs.Flush().ToArray(); Assert.AreEqual(0, records.Count()); }); observer.Connect(div, characterData: true, subtree: true); div.RemoveChild(child); child.TextContent = "changed"; observer.Trigger(); }
public void MutationObserverCharacterdataWithOldValue() { var document = Html(""); var testDiv = document.Body.AppendChild(document.CreateElement("div")); var text = testDiv.AppendChild(document.CreateTextNode("abc")); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(text, characterData: true, characterDataOldValue: true); text.TextContent = "def"; text.TextContent = "ghi"; var records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 2); AssertRecord(records[0], new TestMutationRecord { Type = "characterData", Target = text, PreviousValue = "abc" }); AssertRecord(records[1], new TestMutationRecord { Type = "characterData", Target = text, PreviousValue = "def" }); }
public void MutationObserverAttrAndCharacterdata() { var document = Html(""); var div = document.CreateElement("div"); var text = div.AppendChild(document.CreateTextNode("text")); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(div, attributes: true, subtree: true, characterData: true); div.SetAttribute("a", "A"); div.FirstChild.TextContent = "changed"; var records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 2); AssertRecord(records[0], new TestMutationRecord { Type = "attributes", Target = div, AttributeName = "a", AttributeNamespace = null }); AssertRecord(records[1], new TestMutationRecord { Type = "characterData", Target = div.FirstChild }); }
public void MutationObserverReplaceAllChildrenUsingInnerhtml() { var document = Html(""); var testDiv = document.Body.AppendChild(document.CreateElement("div")); var div = document.CreateElement("div"); testDiv.AppendChild(div); var a = div.AppendChild(document.CreateTextNode("a")); var b = div.AppendChild(document.CreateTextNode("b")); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(div, childList: true); div.InnerHtml = "<c></c><d></d>"; var c = div.FirstChild; var d = div.LastChild; var records = observer.Flush().ToArray(); var merged = MergeRecords(records); AssertArrayEqual(merged.Item1, ToNodeList(c, d)); AssertArrayEqual(merged.Item2, ToNodeList(a, b)); AssertAll(records, new TestMutationRecord { Type = "childList", Target = div }); }
public void MutationObserverAttrCallback() { var document = Html(""); var testDiv = document.Body.AppendChild(document.CreateElement("div")); var div = testDiv.AppendChild(document.CreateElement("div")); var child = document.CreateElement("div"); div.AppendChild(child); var i = 0; var observer = new MutationObserver((records, obs) => { Assert.LessOrEqual(++i, 2); Assert.AreEqual(1, records.Count()); AssertRecord(records[0], new TestMutationRecord { Type = "attributes", Target = child, AttributeName = "a", AttributeNamespace = null }); // The transient observers are removed before the callback is called. child.SetAttribute("b", "B"); records = obs.Flush().ToArray(); Assert.AreEqual(0, records.Count()); }); observer.Connect(div, attributes: true, subtree: true); div.RemoveChild(child); child.SetAttribute("a", "A"); observer.Trigger(); }
public void MutationObserverCharacterdata() { var document = Html("", true); var text = document.CreateTextNode("abc"); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(text, characterData: true); text.TextContent = "def"; text.TextContent = "ghi"; var records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 2); AssertRecord(records[0], new TestMutationRecord { Type = "characterData", Target = text }); AssertRecord(records[1], new TestMutationRecord { Type = "characterData", Target = text }); }
public void MutationObserverCharacterdataChangeInSubtree() { var document = Html(""); var div = document.CreateElement("div"); var text = div.AppendChild(document.CreateTextNode("abc")); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(div, characterData: true, subtree: true); text.TextContent = "def"; text.TextContent = "ghi"; var records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 2); AssertRecord(records[0], new TestMutationRecord { Type = "characterData", Target = text }); AssertRecord(records[1], new TestMutationRecord { Type = "characterData", Target = text }); }
public void MutationObserverAppendMultipleAtOnceInTheMiddle() { var document = Html(""); var testDiv = document.Body.AppendChild(document.CreateElement("div")); var div = document.CreateElement("div"); testDiv.AppendChild(div); var a = div.AppendChild(document.CreateTextNode("a")); var b = div.AppendChild(document.CreateTextNode("b")); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(div, childList: true); var df = document.CreateDocumentFragment(); var c = df.AppendChild(document.CreateTextNode("c")); var d = df.AppendChild(document.CreateTextNode("d")); div.InsertBefore(df, b); var records = observer.Flush().ToArray(); var merged = MergeRecords(records); AssertArrayEqual(merged.Item1, ToNodeList(c, d)); AssertArrayEqual(merged.Item2, ToNodeList()); AssertAll(records, new TestMutationRecord { Type = "childList", Target = div }); }
public void MutationObserverAttrChangeSubtree() { var document = Html(""); var div = document.CreateElement("div"); var child = document.CreateElement("div"); div.AppendChild(child); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(div, attributes: true, subtree: true); child.SetAttribute("a", "A"); child.SetAttribute("a", "B"); var records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 2); AssertRecord(records[0], new TestMutationRecord { Type = "attributes", Target = child, AttributeName = "a" }); AssertRecord(records[1], new TestMutationRecord { Type = "attributes", Target = child, AttributeName = "a" }); }
public void MutationObserverAttrWithOldvalue() { var document = Html(""); var div = document.CreateElement("div"); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(div, attributes: true, attributeOldValue: true); div.SetAttribute("a", "A"); div.SetAttribute("a", "B"); var records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 2); AssertRecord(records[0], new TestMutationRecord { Type = "attributes", Target = div, AttributeName = "a", AttributeNamespace = null, PreviousValue = null }); AssertRecord(records[1], new TestMutationRecord { Type = "attributes", Target = div, AttributeName = "a", AttributeNamespace = null, PreviousValue = "A" }); }
public void ConnectMutationObserverTextWithDescendentsAndExaminingOldValueTriggerManually() { var called = false; var text = "something"; var replaced = "different"; var observer = new MutationObserver((mut, obs) => { called = true; Assert.AreEqual(1, mut.Length); Assert.AreEqual(text, mut[0].PreviousValue); var tn = mut[0].Target as TextNode; Assert.IsNotNull(tn); Assert.AreEqual(text + replaced, tn.TextContent); }); var document = Html(""); observer.Connect(document.Body, characterData: true, subtree: true, characterDataOldValue: true); document.Body.TextContent = text; var textNode = document.Body.ChildNodes[0] as TextNode; textNode.Replace(text.Length, 0, replaced); observer.TriggerWith(observer.Flush().ToArray()); Assert.IsTrue(called); }
public async Task MutationObserverOneObserverTwoAttributeChanges() { var document = Html("", true); var div = document.CreateElement("div"); var tcs = new TaskCompletionSource <Boolean>(); var observer = new MutationObserver((records, obs) => { Assert.AreEqual(records.Count(), 2); AssertRecord(records[0], new TestMutationRecord { Type = "attributes", Target = div, AttributeName = "a", AttributeNamespace = null }); AssertRecord(records[1], new TestMutationRecord { Type = "attributes", Target = div, AttributeName = "a", AttributeNamespace = null }); tcs.SetResult(true); }); observer.Connect(div, attributes: true); div.SetAttribute("a", "A"); div.SetAttribute("a", "B"); await tcs.Task.ConfigureAwait(false); }
public void MutationObserverOneObserverTwoAttributeChanges() { var document = Html(""); var div = document.CreateElement("div"); var observer = new MutationObserver((records, obs) => { Assert.AreEqual(records.Count(), 2); AssertRecord(records[0], new TestMutationRecord { Type = "attributes", Target = div, AttributeName = "a", AttributeNamespace = null }); AssertRecord(records[1], new TestMutationRecord { Type = "attributes", Target = div, AttributeName = "a", AttributeNamespace = null }); }); observer.Connect(div, attributes: true); div.SetAttribute("a", "A"); div.SetAttribute("a", "B"); }
public void MutationObserverChildListCharacterdata() { var document = Html(""); var div = document.CreateElement("div"); var child = div.AppendChild(document.CreateTextNode("text")); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(div, characterData: true, subtree: true); div.RemoveChild(child); child.TextContent = "changed"; var records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 1); AssertRecord(records[0], new TestMutationRecord { Type = "characterData", Target = child }); child.TextContent += " again"; records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 1); AssertRecord(records[0], new TestMutationRecord { Type = "characterData", Target = child }); }
public void MutationObserverObserverObservesOnDifferentTarget() { var document = Html(""); var div = document.CreateElement("div"); var child = document.CreateElement("div"); div.AppendChild(child); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(child, attributes: true); observer.Connect(div, attributes: true, subtree: true, attributeOldValue: true); child.SetAttribute("a", "A"); child.SetAttribute("a", "A2"); child.SetAttribute("b", "B"); var records = observer.Flush().ToArray(); Assert.AreEqual(3, records.Count()); AssertRecord(records[0], new TestMutationRecord { Type = "attributes", Target = child, AttributeName = "a" }); AssertRecord(records[1], new TestMutationRecord { Type = "attributes", Target = child, AttributeName = "a", PreviousValue = "A" }); AssertRecord(records[2], new TestMutationRecord { Type = "attributes", Target = child, AttributeName = "b" }); }
public void MutationObserverObservingOnTheSameNodeShouldUpdateTheOptions() { var document = Html(""); var div = document.CreateElement("div"); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(div, attributes: true, attributeFilter: new[] { "a" }); observer.Connect(div, attributes: true, attributeFilter: new[] { "b" }); div.SetAttribute("a", "A"); div.SetAttribute("b", "B"); var records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 1); AssertRecord(records[0], new TestMutationRecord { Type = "attributes", Target = div, AttributeName = "b" }); }
public void MutationObserverMultipleObserversOnSameTarget() { var document = Html(""); var div = document.CreateElement("div"); var observer1 = new MutationObserver((obs, mut) => { }); observer1.Connect(div, attributes: true, attributeOldValue: true); var observer2 = new MutationObserver((obs, mut) => { }); observer2.Connect(div, attributes: true, attributeFilter: new [] { "b" }); div.SetAttribute("a", "A"); div.SetAttribute("a", "A2"); div.SetAttribute("b", "B"); var records = observer1.Flush().ToArray(); Assert.AreEqual(records.Count(), 3); AssertRecord(records[0], new TestMutationRecord { Type = "attributes", Target = div, AttributeName = "a" }); AssertRecord(records[1], new TestMutationRecord { Type = "attributes", Target = div, AttributeName = "a", PreviousValue = "A" }); AssertRecord(records[2], new TestMutationRecord { Type = "attributes", Target = div, AttributeName = "b" }); records = observer2.Flush().ToArray(); Assert.AreEqual(1, records.Count()); AssertRecord(records[0], new TestMutationRecord { Type = "attributes", Target = div, AttributeName = "b" }); }
public void MutationObserverAttrMakeSureTransientGetsRemoved() { var document = Html(""); var testDiv = document.Body.AppendChild(document.CreateElement("div")); var div = testDiv.AppendChild(document.CreateElement("div")); var child = document.CreateElement("div"); div.AppendChild(child); var i = 0; var observer = new MutationObserver((records, obs) => { Assert.AreNotEqual(2, ++i); Assert.AreEqual(records.Count(), 1); AssertRecord(records[0], new TestMutationRecord { Type = "attributes", Target = child, AttributeName = "a", AttributeNamespace = null }); }); observer.Connect(div, subtree: true, attributes: true); div.RemoveChild(child); child.SetAttribute("a", "A"); observer.Trigger(); var div2 = document.CreateElement("div"); var observer2 = new MutationObserver((records, obs) => { Assert.LessOrEqual(++i, 3); Assert.AreEqual(records.Count(), 1); AssertRecord(records[0], new TestMutationRecord { Type = "attributes", Target = child, AttributeName = "b", AttributeNamespace = null }); }); observer2.Connect(div2, attributes: true, subtree: true); div2.AppendChild(child); child.SetAttribute("b", "B"); observer2.Trigger(); }
public void MutationObserverCharacterdataChangeInSubtreeShouldNotGenerateARecord() { var document = Html(""); var div = document.CreateElement("div"); var text = div.AppendChild(document.CreateTextNode("abc")); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(div, characterData: true); text.TextContent = "def"; text.TextContent = "ghi"; var records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 0); }
public void MutationObserverDisconnectShouldStopAllEventsAndEmptyTheRecords() { var document = Html(""); var div = document.CreateElement("div"); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(div, attributes: true); div.SetAttribute("a", "A"); observer.Disconnect(); var records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 0); div.SetAttribute("b", "B"); records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 0); }
public void ConnectMutationObserverChildNodesTriggerManually() { var called = false; var observer = new MutationObserver((mut, obs) => { called = true; Assert.AreEqual(1, mut.Length); var record = mut[0]; Assert.IsNotNull(record.Added); Assert.AreEqual(1, record.Added.Length); }); var document = Html(""); observer.Connect(document.Body, childList: true); document.Body.AppendChild(document.CreateElement("span")); Assert.IsTrue(called); }
public void MutationObserverAttrChangeInSubtreeShouldNotGenereateARecord() { var document = Html(""); var div = document.CreateElement("div"); var child = document.CreateElement("div"); div.AppendChild(child); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(div, attributes: true); child.SetAttribute("a", "A"); child.SetAttribute("a", "B"); var records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 0); }
public void MutationObserverSubtree() { var document = Html(""); var div = document.CreateElement("div"); var child = div.AppendChild(document.CreateElement("div")); var observer = new MutationObserver((obs, mut) => { }); observer.Connect(child, childList: true); var a = document.CreateTextNode("a"); var b = document.CreateTextNode("b"); child.AppendChild(a); child.InsertBefore(b, a); child.RemoveChild(b); var records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 3); AssertRecord(records[0], new TestMutationRecord { Type = "childList", Target = child, Added = ToNodeList(a) }); AssertRecord(records[1], new TestMutationRecord { Type = "childList", Target = child, NextSibling = a, Added = ToNodeList(b) }); AssertRecord(records[2], new TestMutationRecord { Type = "childList", Target = child, NextSibling = a, Removed = ToNodeList(b) }); }
public async Task MutationObserverChildlistCallback() { var document = Html("", true); var testDiv = document.Body.AppendChild(document.CreateElement("div")); var div = testDiv.AppendChild(document.CreateElement("div")); var child = div.AppendChild(document.CreateElement("div")); var grandChild = document.CreateElement("span"); var i = 0; var tcs = new TaskCompletionSource <Boolean>(); var observer = new MutationObserver((records, obs) => { Assert.LessOrEqual(++i, 2); Assert.AreEqual(2, records.Count()); AssertRecord(records[0], new TestMutationRecord { Type = "childList", Target = div, Removed = ToNodeList(child) }); AssertRecord(records[1], new TestMutationRecord { Type = "childList", Target = child, Added = ToNodeList(grandChild) }); // The transient observers are removed before the callback is called. child.RemoveChild(grandChild); records = obs.Flush().ToArray(); Assert.AreEqual(0, records.Count()); tcs.SetResult(true); }); observer.Connect(div, childList: true, subtree: true); div.RemoveChild(child); child.AppendChild(grandChild); observer.Trigger(); await tcs.Task.ConfigureAwait(false); }
public void MutationObserverChildlist() { var document = Html(""); var testDiv = document.Body.AppendChild(document.CreateElement("div")); var div = testDiv.AppendChild(document.CreateElement("div")); var child = div.AppendChild(document.CreateElement("div")); var observer = new MutationObserver((mut, obs) => { }); observer.Connect(div, childList: true, subtree: true); div.RemoveChild(child); var grandChild = child.AppendChild(document.CreateElement("span")); var records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 2); AssertRecord(records[0], new TestMutationRecord { Type = "childList", Target = div, Removed = ToNodeList(child) }); AssertRecord(records[1], new TestMutationRecord { Type = "childList", Target = child, Added = ToNodeList(grandChild) }); child.RemoveChild(grandChild); records = observer.Flush().ToArray(); Assert.AreEqual(records.Count(), 1); AssertRecord(records[0], new TestMutationRecord { Type = "childList", Target = child, Removed = ToNodeList(grandChild) }); }
public void ConnectMutationObserverMultipleAttributesDescendentTriggerManually() { var called1 = false; var called2 = false; var called3 = false; var attrName = "something"; var attrValue = "test"; var document = Html(""); var observer1 = new MutationObserver((mut, obs) => { called1 = true; Assert.AreEqual(1, mut.Length); }); observer1.Connect(document.DocumentElement, attributes: true, subtree: true); var observer2 = new MutationObserver((mut, obs) => { called2 = true; Assert.AreEqual(0, mut.Length); }); observer2.Connect(document.DocumentElement, attributes: true, subtree: false); var observer3 = new MutationObserver((mut, obs) => { called3 = true; Assert.AreEqual(1, mut.Length); }); observer3.Connect(document.Body, attributes: true); document.Body.SetAttribute(attrName, attrValue); observer1.TriggerWith(observer1.Flush().ToArray()); observer2.TriggerWith(observer2.Flush().ToArray()); observer3.TriggerWith(observer3.Flush().ToArray()); Assert.IsTrue(called1); Assert.IsTrue(called2); Assert.IsTrue(called3); }
public void MutationObserverDisconnectShouldNotAffectOtherObservers() { var document = Html(""); var div = document.CreateElement("div"); var observer1 = new MutationObserver((obs, mut) => { }); observer1.Connect(div, attributes: true); var observer2 = new MutationObserver((obs, mut) => { }); observer2.Connect(div, attributes: true); div.SetAttribute("a", "A"); observer1.Disconnect(); var records1 = observer1.Flush().ToArray(); Assert.AreEqual(records1.Count(), 0); var records2 = observer2.Flush().ToArray(); Assert.AreEqual(records2.Count(), 1); AssertRecord(records2[0], new TestMutationRecord { Type = "attributes", Target = div, AttributeName = "a" }); div.SetAttribute("b", "B"); records1 = observer1.Flush().ToArray(); Assert.AreEqual(records1.Count(), 0); records2 = observer2.Flush().ToArray(); Assert.AreEqual(records2.Count(), 1); AssertRecord(records2[0], new TestMutationRecord { Type = "attributes", Target = div, AttributeName = "b" }); }
public void ConnectMutationObserverTextNoDescendentsButCreatedTriggerManually() { var called = false; var text = "something"; var observer = new MutationObserver((mut, obs) => { called = true; Assert.AreEqual(1, mut.Length); Assert.AreEqual(1, mut[0].Added.Length); Assert.AreEqual(text, mut[0].Added[0].TextContent); }); var document = Html(""); observer.Connect(document.Body, subtree: false, childList: true); document.Body.TextContent = text; Assert.IsTrue(called); }
public void ConnectMutationObserverAttributesTriggerManually() { var called = false; var attrName = "something"; var attrValue = "test"; var observer = new MutationObserver((mut, obs) => { called = true; Assert.AreEqual(1, mut.Length); Assert.AreEqual(attrName, mut[0].AttributeName); Assert.IsNull(mut[0].PreviousValue); }); var document = Html(""); observer.Connect(document.Body, attributes: true); document.Body.SetAttribute(attrName, attrValue); Assert.IsTrue(called); }