public void Container_RemoveContent_NullNode_Throws(Fb2Container node) { var firstAllowedNode = Fb2NodeFactory.GetNodeByName(node.AllowedElements.First()); node.Invoking(n => n.RemoveContent((Fb2Node)null)) // Fb2Node .Should() .ThrowExactly <ArgumentNullException>(); node.Invoking(n => n.RemoveContent((IEnumerable <Fb2Node>)null)) // IEnumerable<Fb2Node> .Should() .ThrowExactly <ArgumentNullException>(); node.Invoking(n => n.RemoveContent((Func <Fb2Node, bool>)null)) // Func<Fb2Node, bool> .Should() .ThrowExactly <ArgumentNullException>(); node.Invoking(n => n.RemoveContent(new List <Fb2Node> { null, null })) // IEnumerable<Fb2Node> .Should() .ThrowExactly <ArgumentNullException>(); node.Invoking(n => n.RemoveContent(new List <Fb2Node> { firstAllowedNode, null })) // IEnumerable<Fb2Node> .Should() .ThrowExactly <ArgumentNullException>(); }
public virtual IEnumerator <object[]> GetEnumerator() { return(AllElementsNames .Select(name => new object[1] { Fb2NodeFactory.GetNodeByName(name) }) .GetEnumerator()); }
public void GetElementByNodeName_InvalidNodeName_Throws() { var invalidNodeName = "invalidNodeName"; Action act = () => { var node = Fb2NodeFactory.GetNodeByName(invalidNodeName); }; act.Should().Throw <InvalidNodeException>() .WithMessage($"'{invalidNodeName}' is not known Fb2 node name."); }
public void Container_AddContent_NullNode_Throws(Fb2Container node) { node.Should().NotBeNull(); var firstAllowedNode = Fb2NodeFactory.GetNodeByName(node.AllowedElements.First()); node.Invoking(n => n.AddContent((Fb2Node)null)) // Fb2Node .Should() .Throw <ArgumentNullException>(); //string nodeName node.Invoking(n => n.AddContent("")).Should().Throw <ArgumentNullException>(); //string nodeName node.Invoking(n => n.AddContent((string)null)).Should().Throw <ArgumentNullException>(); // params Fb2Node[] nodes node.Invoking(n => n.AddContent()).Should().Throw <ArgumentNullException>(); // params Fb2Node[] nodes node.Invoking(n => n.AddContent(null, null)) // lol .Should() .Throw <ArgumentNullException>(); node.Invoking(n => n.AddContent(() => null)) // Func<Fb2Node> .Should() .Throw <ArgumentNullException>(); node.Invoking(n => n.AddContent((Func <Fb2Node>)null)) // Func<Fb2Node> .Should() .Throw <ArgumentNullException>(); node.Invoking(n => n.AddContent((List <Fb2Node>)null)) // IEnumerable<Fb2Node> .Should() .Throw <ArgumentNullException>(); node.Invoking(n => n.AddContent(new List <Fb2Node> { null, null })) // IEnumerable<Fb2Node> .Should() .Throw <ArgumentNullException>(); node.Invoking(n => n.AddContent(new List <Fb2Node> { firstAllowedNode, null })) // IEnumerable<Fb2Node> .Should() .Throw <ArgumentNullException>(); node.Invoking(async n => await n.AddContentAsync( async() => await Task.FromResult <Fb2Node>(null))) // async node provider .Should() .ThrowExactlyAsync <ArgumentNullException>(); node.Invoking(async n => await n.AddContentAsync(null)) .Should() .ThrowExactlyAsync <ArgumentNullException>(); }
public void EmptyNodes_EqualityNullTest(Fb2Node instance) { instance.Should().NotBe(null); var instanceTwo = Fb2NodeFactory.GetNodeByName(instance.Name); instanceTwo.Should().NotBe(null); instance.Should().Be(instanceTwo); }
public void IsKnownNode_ImpostorNode_ReturnsFalse() { var impostor = new ImpostorNode(); Fb2NodeFactory.IsKnownNode(impostor).Should().BeFalse(); var sneakyImpostor = new ImpostorNode(ElementNames.Paragraph); Fb2NodeFactory.IsKnownNode(sneakyImpostor).Should().BeFalse(); }
/// <summary> /// Adds new node to <see cref="Content"/> using node's `Name`. /// </summary> /// <param name="nodeName">Name to instantiate node by.</param> /// <returns>Current container.</returns> /// <exception cref="ArgumentNullException"></exception> public Fb2Container AddContent(string nodeName) { if (string.IsNullOrWhiteSpace(nodeName)) { throw new ArgumentNullException(nameof(nodeName)); } var node = Fb2NodeFactory.GetNodeByName(nodeName); return(AddContent(node)); }
public void EmptyLine_AddTextContent_IsIgnored() { var emptyLine = Fb2NodeFactory.GetNodeByName(ElementNames.EmptyLine) as Fb2Element; emptyLine.Should().NotBeNull(); emptyLine.Content.Should().Be(Environment.NewLine); emptyLine.AddContent("test content", " "); emptyLine.Content.Should().Be(Environment.NewLine); emptyLine.AddContent(() => "test content", " "); emptyLine.Content.Should().Be(Environment.NewLine); }
/// <summary> /// Gets first matching child of element by given name. /// </summary> /// <param name="name">Name to select child element by. Optional.</param> /// <returns>First matched child node or <see langword="null"/>.</returns> /// <exception cref="InvalidNodeException"></exception> public Fb2Node?GetFirstChild(string?name) { if (!string.IsNullOrEmpty(name) && !Fb2NodeFactory.IsKnownNodeName(name)) { throw new InvalidNodeException(name); } if (IsEmpty) { return(null); } return(string.IsNullOrWhiteSpace(name) ? content.FirstOrDefault() : content.FirstOrDefault(elem => elem.Name.EqualsIgnoreCase(name))); }
public void ValidNodeName_CaseInvariantNodeName_Works() { var titleInfoCasedNodeName = "tItLe-iNFo"; var strikethroughCasedNodeName = "sTrIkEtHrOuGh"; Fb2NodeFactory.IsKnownNodeName(titleInfoCasedNodeName).Should().BeTrue(); Fb2NodeFactory.IsKnownNodeName(strikethroughCasedNodeName).Should().BeTrue(); var titleInfo = Fb2NodeFactory.GetNodeByName(titleInfoCasedNodeName); var strikethrough = Fb2NodeFactory.GetNodeByName(strikethroughCasedNodeName); titleInfo.Should().NotBeNull(); strikethrough.Should().NotBeNull(); titleInfo.Name.Should().Be(ElementNames.TitleInfo); strikethrough.Name.Should().Be(ElementNames.Strikethrough); }
public async Task Container_AddContent_AllowedElement_Works(Fb2Container node) { node.Should().NotBeNull(); var allowedElementName = node.AllowedElements.First(); var firstAllowedNode = Fb2NodeFactory.GetNodeByName(allowedElementName); node.AddContent(firstAllowedNode); node.Content.Should().NotBeEmpty().And.Subject.Should().HaveCount(1); ClearContainerContent(node); // params Fb2Node[] nodes node.AddContent(firstAllowedNode, firstAllowedNode); // lol node.Content.Should().NotBeEmpty().And.Subject.Should().HaveCount(2); ClearContainerContent(node); node.AddContent(() => firstAllowedNode); // Func<Fb2Node> node.Content.Should().NotBeEmpty().And.Subject.Should().HaveCount(1); ClearContainerContent(node); node.AddContent(new List <Fb2Node> { firstAllowedNode }); // IEnumerable<Fb2Node> node.Content.Should().NotBeEmpty().And.Subject.Should().HaveCount(1); ClearContainerContent(node); // async node provider await node.AddContentAsync(async() => await Task.FromResult(firstAllowedNode)); node.Content.Should().NotBeEmpty().And.Subject.Should().HaveCount(1); ClearContainerContent(node); //string name node.AddContent(node.AllowedElements.First()); node.Content.Should().HaveCount(1); }
public void Container_AddContent_NotAllowedElement_Throws(Fb2Container node) { node.Should().NotBeNull(); var dataCollection = new Fb2ContainerCollection(); var notAllowedElementName = dataCollection.AllElementsNames.Except(node.AllowedElements).Skip(5).First(); var notAllowedNode = Fb2NodeFactory.GetNodeByName(notAllowedElementName); node.Invoking(n => n.AddContent(notAllowedNode.Name)) // string nodeName .Should() .Throw <UnexpectedNodeException>() .WithMessage($"Node '{node.Name}' can not contain '{notAllowedNode.Name}'."); node.Invoking(n => n.AddContent(notAllowedNode)) // Fb2Node .Should() .Throw <UnexpectedNodeException>() .WithMessage($"Node '{node.Name}' can not contain '{notAllowedNode.Name}'."); // params Fb2Node[] nodes node.Invoking(n => n.AddContent(notAllowedNode, notAllowedNode)) // lol .Should() .Throw <UnexpectedNodeException>() .WithMessage($"Node '{node.Name}' can not contain '{notAllowedNode.Name}'."); node.Invoking(n => n.AddContent(() => notAllowedNode)) // Func<Fb2Node> .Should() .Throw <UnexpectedNodeException>() .WithMessage($"Node '{node.Name}' can not contain '{notAllowedNode.Name}'."); node.Invoking(n => n.AddContent(new List <Fb2Node> { notAllowedNode })) // IEnumerable<Fb2Node> .Should() .Throw <UnexpectedNodeException>() .WithMessage($"Node '{node.Name}' can not contain '{notAllowedNode.Name}'."); node.Invoking(async n => await n.AddContentAsync(async() => await Task.FromResult(notAllowedNode))) // async node provider .Should() .ThrowExactlyAsync <UnexpectedNodeException>() .WithMessage($"Node '{node.Name}' can not contain '{notAllowedNode.Name}'."); }
/// <summary> /// Gets children of element by given name. /// </summary> /// <param name="name">Name to select child elements by. Case insensitive.</param> /// <returns>List of found child elements, if any.</returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="InvalidNodeException"></exception> public IEnumerable <Fb2Node> GetChildren(string name) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentNullException(nameof(name)); } if (!Fb2NodeFactory.IsKnownNodeName(name)) { throw new InvalidNodeException(name); } if (IsEmpty) { return(Enumerable.Empty <Fb2Node>()); } return(content.Where(elem => elem.Name.EqualsIgnoreCase(name))); }
/// <summary> /// Recursively gets all descendants of element by given name. /// </summary> /// <param name="name">Name to select descendants by.</param> /// <returns>List of found descendants, if any.</returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="InvalidNodeException"></exception> public IEnumerable <Fb2Node> GetDescendants(string name) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentNullException(nameof(name)); } if (!Fb2NodeFactory.IsKnownNodeName(name)) { throw new InvalidNodeException(name); } var result = new List <Fb2Node>(); if (IsEmpty) { return(result); } for (int i = 0; i < content.Count; i++) { var element = content[i]; if (element.Name.EqualsIgnoreCase(name)) { result.Add(element); } if (element is Fb2Container containerElement) { var desc = containerElement.GetDescendants(name); if (desc != null && desc.Any()) { result.AddRange(desc); } } } return(result); }
/// <summary> /// Adds given node to <see cref="Content"/>. /// </summary> /// <param name="node">Child node to add to Content.</param> /// <returns>Current container.</returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="InvalidNodeException"></exception> /// <exception cref="UnexpectedNodeException"></exception> public Fb2Container AddContent(Fb2Node node) { if (node == null) { throw new ArgumentNullException(nameof(node)); } if (!Fb2NodeFactory.IsKnownNode(node)) { throw new InvalidNodeException(node); } var nodeName = node.Name; var isTextNode = node is TextItem; if (isTextNode && !CanContainText) { throw new UnexpectedNodeException(Name, nodeName); } if (!AllowedElements.Contains(nodeName) && !isTextNode) { throw new UnexpectedNodeException(Name, nodeName); } if (isTextNode) { return(TryMergeTextContent((node as TextItem) !.Content)); } node.Parent = this; if (node.NodeMetadata == null && NodeMetadata?.DefaultNamespace != null) // copy parent default namespace to prevent serialization issues { node.NodeMetadata = new Fb2NodeMetadata(NodeMetadata?.DefaultNamespace); } content.Add(node); return(this); }
/// <summary> /// Recursively looks for first matching descendant of element by given name. /// </summary> /// <param name="name">Name to select descendant by.</param> /// <returns>First matching descendant node or <see langword="null"/>.</returns> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="InvalidNodeException"></exception> public Fb2Node?GetFirstDescendant(string name) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentNullException(nameof(name)); } if (!Fb2NodeFactory.IsKnownNodeName(name)) { throw new InvalidNodeException(name); } if (IsEmpty) { return(null); } for (int i = 0; i < content.Count; i++) { var element = content[i]; if (element.Name.EqualsIgnoreCase(name)) { return(element); } if (element is Fb2Container containerElement) { var firstDesc = containerElement.GetFirstDescendant(name); if (firstDesc != null) { return(firstDesc); } } } return(null); }
public void CloneNode_EqualityTest(Fb2Node instance) { var instanceTwo = Fb2NodeFactory.GetNodeByName(instance.Name); instance.Should().Be(instanceTwo); }
public void IsKnownNode_ValidNode_ReturnsTrue(Fb2Node node) { Fb2NodeFactory.IsKnownNode(node).Should().BeTrue(); }
public void IsKnownNodeName_ValidNodeName_ReturnsTrue(string nodeName) { Fb2NodeFactory.IsKnownNodeName(nodeName).Should().BeTrue(); }
public void IsKnownNodeName_InvalidNodeName_ReturnsFalse() { var invalidNodeName = "invalidNodeName"; Fb2NodeFactory.IsKnownNodeName(invalidNodeName).Should().BeFalse(); }
public void Container_RemoveContent_ExistingElement_Works(Fb2Container node) { node.Should().NotBeNull(); var firstAllowedNode = Fb2NodeFactory.GetNodeByName(node.AllowedElements.First()); var lastAllowedNode = Fb2NodeFactory.GetNodeByName(node.AllowedElements.Last()); var nodesEquals = firstAllowedNode.Equals(lastAllowedNode); node.AddContent(firstAllowedNode, lastAllowedNode); node.Content.Should().NotBeEmpty().And.Subject.Should().HaveCount(2); firstAllowedNode.Parent.Should().NotBeNull(); firstAllowedNode.Parent.Should().Be(node); lastAllowedNode.Parent.Should().NotBeNull(); lastAllowedNode.Parent.Should().Be(node); node.RemoveContent(firstAllowedNode); // Fb2Node firstAllowedNode.Parent.Should().BeNull(); node.Content.Should().NotBeEmpty().And.Subject.Should().HaveCount(1); node.Content.Should().Contain(lastAllowedNode); // empty nodes (without sub tree) of same type are, basically, equal lol // so if you add 2 empty "bold" elements to "paragraph" // and then use RemoveContent(firstAllowedNode), and check Contains - it will return true if (!nodesEquals) // when container can have only one type child { node.Content.Contains(firstAllowedNode).Should().BeFalse(); } ClearContainerContent(node); lastAllowedNode.Parent.Should().BeNull(); node.AddContent(firstAllowedNode, lastAllowedNode); node.Content.Should().NotBeEmpty().And.Subject.Should().HaveCount(2); firstAllowedNode.Parent.Should().NotBeNull(); firstAllowedNode.Parent.Should().Be(node); lastAllowedNode.Parent.Should().NotBeNull(); lastAllowedNode.Parent.Should().Be(node); node.RemoveContent(new List <Fb2Node> { firstAllowedNode, lastAllowedNode }); // IEnumerable<Fb2Node> node.Content.Should().BeEmpty(); node.AddContent(firstAllowedNode, lastAllowedNode); node.Content.Should().NotBeEmpty().And.Subject.Should().HaveCount(2); node.RemoveContent(n => n.Name.Equals(firstAllowedNode.Name)); // Func<Fb2Node, bool> predicate if (nodesEquals) { node.Content.Should().BeEmpty(); } else { node.Content.Should().NotBeEmpty().And.Subject.Should().HaveCount(1); node.Content.Should().Contain(lastAllowedNode); node.Content.Should().NotContain(firstAllowedNode); } ClearContainerContent(node); }
/// <summary> /// Container node loading mechanism. Loads attributes and sequentially calls `Load` on all child nodes. /// </summary> /// <param name="node">Node to load as Fb2Container</param> /// <param name="preserveWhitespace">Indicates if whitespace chars (\t, \n, \r) should be preserved. By default `false`.</param> /// <param name="loadUnsafe">Indicates whether "Unsafe" children should be loaded. By default `true`. </param> public override void Load( [In] XNode node, [In] Fb2Container?parentNode = null, bool preserveWhitespace = false, bool loadUnsafe = true, bool loadNamespaceMetadata = true) { base.Load(node, parentNode, preserveWhitespace, loadUnsafe, loadNamespaceMetadata); var element = node as XElement; if (element == null || element.IsEmpty) { return; } var nodes = element.Nodes() .Where(n => { if (n.NodeType == XmlNodeType.Text) { return(true); } var isElement = n.NodeType == XmlNodeType.Element; if (!isElement) { return(false); } var elementNode = n as XElement; var nodeLocalName = elementNode.Name.LocalName; return(!nodeLocalName.EqualsIgnoreCase(ElementNames.FictionText) && Fb2NodeFactory.IsKnownNodeName(nodeLocalName)); }) .ToList(); var nodesCount = nodes.Count; if (nodesCount == 0) { return; } for (int i = 0; i < nodesCount; i++) { var validNode = nodes[i]; string localName = validNode.NodeType == XmlNodeType.Element ? ((XElement)validNode).Name.LocalName.ToLowerInvariant() : ElementNames.FictionText; var isUnsafe = validNode.NodeType == XmlNodeType.Text ? !CanContainText : !AllowedElements.Contains(localName); if (isUnsafe && !loadUnsafe) { continue; } var elem = Fb2NodeFactory.GetNodeByName(localName); elem.Load(validNode, this, preserveWhitespace, loadUnsafe, loadNamespaceMetadata); elem.IsUnsafe = isUnsafe; content.Add(elem); } }