+ // | | |
+ // +--------+-------+ "World"
+ // | | |
+ //
+-----+-----+
+ // | | | |
+ // +-------+-------+ "Hello" "Another"
+ // | | |
+ // "This " " text" |
+ // | "Text"
+ // "is a"
+ //
+ //
+ return [HTMLDocument documentWithString:
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"];
+}
+
+#pragma mark - Delete Contents
+
+- (void)testDeleteContents_SameTextNode
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:1];
+ HTMLNode *end = [document querySelector:@"#P1"].firstChild;
+ [range setEndNode:end endOffset:4];
+ [range deleteContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+}
+
+- (void)testDeleteContents_SameTextNode_Selected
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *node = [document querySelector:@"#P1"].firstChild;
+ [range selectNode:node];
+ [range deleteContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+
+ XCTAssertEqual([document querySelector:@"#P1"].childNodesCount, 2);
+}
+
+- (void)testDeleteContents_SameTextNode_SelectedContents
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *node = [document querySelector:@"#P1"].firstChild;
+ [range selectNodeContents:node];
+ [range deleteContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+
+ XCTAssertEqual([document querySelector:@"#P1"].childNodesCount, 3);
+ XCTAssertEqual([document querySelector:@"#P1"].firstChild.nodeType, HTMLNodeText);
+}
+
+- (void)testDeleteContents_DifferentTextNodesOfSingleParent
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:3];
+ HTMLNode *end = [document querySelector:@"#P1"].lastChild;
+ [range setEndNode:end endOffset:2];
+ [range deleteContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+}
+
+- (void)testDeleteContents_DifferentTextNodesOfDifferentParents
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:3];
+ HTMLNode *end = [document querySelector:@"#P2"].lastChild;
+ [range setEndNode:end endOffset:4];
+ [range deleteContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+}
+
+- (void)testDeleteContents_DifferentTextNodesOfDifferentParents_HavingContainedNodesInBetween
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:3];
+ HTMLNode *end = [document querySelector:@"#P4"].firstChild;
+ [range setEndNode:end endOffset:2];
+ [range deleteContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""));
+}
+
+- (void)testDeleteContents_SameContainerNode
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"];
+ [range setStartNode:start startOffset:0];
+ HTMLNode *end = [document querySelector:@"#P1"];
+ [range setEndNode:end endOffset:2];
+ [range deleteContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+}
+
+- (void)testDeleteContents_SameContainerNode_Selected
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *node = [document querySelector:@"#P1"];
+ [range selectNode:node];
+ [range deleteContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+}
+
+- (void)testDeleteContents_SameContainerNode_SelectedContents
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *node = [document querySelector:@"#P1"];
+ [range selectNodeContents:node];
+ [range deleteContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+}
+
+- (void)testDeleteContents_StartContainerIsCommonRoot
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#D1"];
+ [range setStartNode:start startOffset:0];
+ HTMLNode *end = [document querySelector:@"#P2"].firstChild;
+ [range setEndNode:end endOffset:2];
+ [range deleteContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+}
+
+- (void)testDeleteContents_EndContainerIsCommonRoot
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:1];
+ HTMLNode *end = [document querySelector:@"#D1"];
+ [range setEndNode:end endOffset:1];
+ [range deleteContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+}
+
+#pragma mark - Clone Contents
+
+- (void)testCloneContents_SameTextNode
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:1];
+ HTMLNode *end = [document querySelector:@"#P1"].firstChild;
+ [range setEndNode:end endOffset:4];
+ HTMLDocumentFragment *fragment = [range cloneContents];
+
+ XCTAssertEqualObjects(fragment.innerHTML, @"his");
+ XCTAssertEqual(fragment.childNodesCount, 1);
+ XCTAssertEqual(fragment.firstChild.nodeType, HTMLNodeText);
+}
+
+- (void)testCloneContents_SameTextNode_Selected
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *node = [document querySelector:@"#P1"].firstChild;
+ [range selectNode:node];
+ HTMLDocumentFragment *fragment = [range cloneContents];
+
+ XCTAssertEqualObjects(fragment.innerHTML, @"This ");
+ XCTAssertEqual(fragment.childNodesCount, 1);
+ XCTAssertEqual(fragment.firstChild.nodeType, HTMLNodeText);
+}
+
+- (void)testCloneContents_SameTextNode_SelectedContents
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *node = [document querySelector:@"#P1"].firstChild;
+ [range selectNodeContents:node];
+ HTMLDocumentFragment *fragment = [range cloneContents];
+
+ XCTAssertEqualObjects(fragment.innerHTML, @"This ");
+ XCTAssertEqual(fragment.childNodesCount, 1);
+ XCTAssertEqual(fragment.firstChild.nodeType, HTMLNodeText);
+}
+
+- (void)testCloneContents_DifferentTextNodesOfSingleParent
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:3];
+ HTMLNode *end = [document querySelector:@"#P1"].lastChild;
+ [range setEndNode:end endOffset:2];
+ HTMLDocumentFragment *fragment = [range cloneContents];
+
+ XCTAssertEqualObjects(fragment.innerHTML, @"s is a t");
+}
+
+- (void)testCloneContents_DifferentTextNodesOfDifferentParents
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:3];
+ HTMLNode *end = [document querySelector:@"#P2"].lastChild;
+ [range setEndNode:end endOffset:4];
+ HTMLDocumentFragment *fragment = [range cloneContents];
+
+ XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"s is a text
Hell
"));
+}
+
+- (void)testCloneContents_DifferentTextNodesOfDifferentParents_HavingContainedNodesInBetween
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:3];
+ HTMLNode *end = [document querySelector:@"#P4"].firstChild;
+ [range setEndNode:end endOffset:2];
+ HTMLDocumentFragment *fragment = [range cloneContents];
+
+ XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@""
+ @"World
"
+ @""));
+}
+
+- (void)testCloneContents_SameContainerNode
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"];
+ [range setStartNode:start startOffset:0];
+ HTMLNode *end = [document querySelector:@"#P1"];
+ [range setEndNode:end endOffset:2];
+ HTMLDocumentFragment *fragment = [range cloneContents];
+
+ XCTAssertEqualObjects(fragment.innerHTML, @"This is a");
+}
+
+- (void)testCloneContents_SameContainerNode_Selected
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *node = [document querySelector:@"#P1"];
+ [range selectNode:node];
+ HTMLDocumentFragment *fragment = [range cloneContents];
+
+ XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"This is a text
"));
+}
+
+- (void)testCloneContents_SameContainerNode_SelectedContents
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *node = [document querySelector:@"#P1"];
+ [range selectNodeContents:node];
+ HTMLDocumentFragment *fragment = [range cloneContents];
+
+ XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"This is a text"));
+}
+
+- (void)testCloneContents_StartContainerIsCommonRoot
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#D1"];
+ [range setStartNode:start startOffset:0];
+ HTMLNode *end = [document querySelector:@"#P2"].firstChild;
+ [range setEndNode:end endOffset:2];
+ HTMLDocumentFragment *fragment = [range cloneContents];
+
+ XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"This is a text
He
"));
+}
+
+- (void)testCloneContents_EndContainerIsCommonRoot
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:1];
+ HTMLNode *end = [document querySelector:@"#D1"];
+ [range setEndNode:end endOffset:1];
+ HTMLDocumentFragment *fragment = [range cloneContents];
+
+ XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"his is a text
"));
+}
+
+#pragma mark - Extract Contents
+
+- (void)testExtractContents_SameTextNode
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:1];
+ HTMLNode *end = [document querySelector:@"#P1"].firstChild;
+ [range setEndNode:end endOffset:4];
+ HTMLDocumentFragment *fragment = [range extractContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+
+ XCTAssertEqualObjects(fragment.innerHTML, @"his");
+ XCTAssertEqual(fragment.childNodesCount, 1);
+ XCTAssertEqual(fragment.firstChild.nodeType, HTMLNodeText);
+}
+
+- (void)testExtractContents_SameTextNode_Selected
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *node = [document querySelector:@"#P1"].firstChild;
+ [range selectNode:node];
+ HTMLDocumentFragment *fragment = [range extractContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+
+ XCTAssertEqual([document querySelector:@"#P1"].childNodesCount, 2);
+
+ XCTAssertEqualObjects(fragment.innerHTML, @"This ");
+ XCTAssertEqual(fragment.childNodesCount, 1);
+ XCTAssertEqual(fragment.firstChild.nodeType, HTMLNodeText);
+}
+
+- (void)testExtractContents_SameTextNode_SelectedContents
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *node = [document querySelector:@"#P1"].firstChild;
+ [range selectNodeContents:node];
+ HTMLDocumentFragment *fragment = [range extractContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+
+ XCTAssertEqual([document querySelector:@"#P1"].childNodesCount, 3);
+ XCTAssertEqual([document querySelector:@"#P1"].firstChild.nodeType, HTMLNodeText);
+
+ XCTAssertEqualObjects(fragment.innerHTML, @"This ");
+ XCTAssertEqual(fragment.childNodesCount, 1);
+ XCTAssertEqual(fragment.firstChild.nodeType, HTMLNodeText);
+}
+
+- (void)testExtractContents_DifferentTextNodesOfSingleParent
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:3];
+ HTMLNode *end = [document querySelector:@"#P1"].lastChild;
+ [range setEndNode:end endOffset:2];
+ HTMLDocumentFragment *fragment = [range extractContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+
+ XCTAssertEqualObjects(fragment.innerHTML, @"s is a t");
+}
+
+- (void)testExtractContents_DifferentTextNodesOfDifferentParents
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:3];
+ HTMLNode *end = [document querySelector:@"#P2"].lastChild;
+ [range setEndNode:end endOffset:4];
+ HTMLDocumentFragment *fragment = [range extractContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+
+ XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"s is a text
Hell
"));
+}
+
+- (void)testExtractContents_DifferentTextNodesOfDifferentParents_HavingContainedNodesInBetween
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:3];
+ HTMLNode *end = [document querySelector:@"#P4"].firstChild;
+ [range setEndNode:end endOffset:2];
+ HTMLDocumentFragment *fragment = [range extractContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""));
+
+ XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@""
+ @"World
"
+ @""));
+}
+
+- (void)testExtractContents_SameContainerNode
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"];
+ [range setStartNode:start startOffset:0];
+ HTMLNode *end = [document querySelector:@"#P1"];
+ [range setEndNode:end endOffset:2];
+ HTMLDocumentFragment *fragment = [range extractContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+
+ XCTAssertEqualObjects(fragment.innerHTML, @"This is a");
+}
+
+- (void)testExtractContents_SameContainerNode_Selected
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *node = [document querySelector:@"#P1"];
+ [range selectNode:node];
+ HTMLDocumentFragment *fragment = [range extractContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+
+ XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"This is a text
"));
+}
+
+- (void)testExtractContents_SameContainerNode_SelectedContents
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *node = [document querySelector:@"#P1"];
+ [range selectNodeContents:node];
+ HTMLDocumentFragment *fragment = [range extractContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+
+ XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"This is a text"));
+}
+
+- (void)testExtractContents_StartContainerIsCommonRoot
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#D1"];
+ [range setStartNode:start startOffset:0];
+ HTMLNode *end = [document querySelector:@"#P2"].firstChild;
+ [range setEndNode:end endOffset:2];
+ HTMLDocumentFragment *fragment = [range extractContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+
+ XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"This is a text
He
"));
+}
+
+- (void)testExtractContents_EndContainerIsCommonRoot
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:1];
+ HTMLNode *end = [document querySelector:@"#D1"];
+ [range setEndNode:end endOffset:1];
+ HTMLDocumentFragment *fragment = [range extractContents];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+
+ XCTAssertEqualObjects(fragment.innerHTML, DoubleQuote(@"his is a text
"));
+}
+
+#pragma mark - Insertion & Surround
+
+- (void)testInsertNode_InvalidNode
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:2];
+ HTMLNode *end = [document querySelector:@"#P1"].lastChild;
+ [range setEndNode:end endOffset:5];
+
+ XCTAssertThrows([range insertNode:start]);
+
+ HTMLComment *comment = [[HTMLComment alloc] initWithData:@"data"];
+ [[document querySelector:@"#D1"] appendNode: comment];
+ [range setStartNode:comment startOffset:2];
+
+ XCTAssertThrows([range insertNode:end]);
+}
+
+- (void)testInsertNode_TextNodeStart_Begin
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:0];
+ HTMLNode *end = [document querySelector:@"#P1"].lastChild;
+ [range setEndNode:end endOffset:5];
+
+ HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div"];
+ [div appendNodes:@[
+ [[HTMLText alloc] initWithData:@"TEXT"],
+ [[HTMLElement alloc] initWithTagName:@"a"]]];
+
+ [range insertNode:div];
+
+ XCTAssertEqualObjects(BodyOf(document), DoubleQuote(@""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+}
+
+- (void)testInsertNode_TextNodeStart_Middle
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:2];
+ HTMLNode *end = [document querySelector:@"#P1"].lastChild;
+ [range setEndNode:end endOffset:5];
+
+ HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div"];
+ [div appendNodes:@[
+ [[HTMLText alloc] initWithData:@"TEXT"],
+ [[HTMLElement alloc] initWithTagName:@"a"]]];
+
+ [range insertNode:div];
+
+ XCTAssertEqualObjects(BodyOf(document), DoubleQuote(@""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+}
+
+- (void)testInsertNode_NonTextNodeStart_Begin
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"];
+ [range setStartNode:start startOffset:0];
+ HTMLNode *end = [document querySelector:@"#P1"].lastChild;
+ [range setEndNode:end endOffset:5];
+
+ HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div"];
+ [div appendNodes:@[
+ [[HTMLText alloc] initWithData:@"TEXT"],
+ [[HTMLElement alloc] initWithTagName:@"a"]]];
+
+ [range insertNode:div];
+
+ XCTAssertEqualObjects(BodyOf(document), DoubleQuote(@""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+}
+
+- (void)testInsertNode_NonTextNodeStart_Middle
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"];
+ [range setStartNode:start startOffset:2];
+ HTMLNode *end = [document querySelector:@"#P1"].lastChild;
+ [range setEndNode:end endOffset:5];
+
+ HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div"];
+ [div appendNodes:@[
+ [[HTMLText alloc] initWithData:@"TEXT"],
+ [[HTMLElement alloc] initWithTagName:@"a"]]];
+
+ [range insertNode:div];
+
+ XCTAssertEqualObjects(BodyOf(document), DoubleQuote(@""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+}
+
+- (void)testInsertNode_NonTextNodeStart_DifferentParents
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#D1"];
+ [range setStartNode:start startOffset:1];
+ HTMLNode *end = [document querySelector:@"#P3"].firstChild;
+ [range setEndNode:end endOffset:4];
+
+ HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div"];
+ [div appendNodes:@[
+ [[HTMLText alloc] initWithData:@"TEXT"],
+ [[HTMLElement alloc] initWithTagName:@"a"]]];
+
+ [range insertNode:div];
+
+ XCTAssertEqualObjects(BodyOf(document), DoubleQuote(@""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+}
+
+- (void)testSurroundContents_InvalidNode
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:2];
+ HTMLNode *end = [document querySelector:@"#P1"].lastChild;
+ [range setEndNode:end endOffset:5];
+
+ XCTAssertThrows([range surroundContents:[HTMLDocumentType new]]);
+ XCTAssertThrows([range surroundContents:[HTMLDocument new]]);
+ XCTAssertThrows([range surroundContents:[[HTMLDocumentFragment alloc] initWithDocument:document]]);
+}
+
+- (void)testSurroundContents_PartiallySelectedAncestors
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:2];
+ HTMLNode *end = [document querySelector:@"#P3"].lastChild;
+ [range setEndNode:end endOffset:3];
+
+ HTMLElement *span = [[HTMLElement alloc] initWithTagName:@"span"];
+ XCTAssertThrows([range surroundContents:span]);
+
+ start = [document querySelector:@"#D1"];
+ [range setStartNode:start startOffset:0];
+ end = [document querySelector:@"#D2"];
+ [range setEndNode:end endOffset:1];
+
+ XCTAssertThrows([range surroundContents:span]);
+}
+
+- (void)testSurroundContents_TextNodes
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:2];
+ HTMLNode *end = [document querySelector:@"#P1"].lastChild;
+ [range setEndNode:end endOffset:3];
+
+ HTMLElement *span = [[HTMLElement alloc] initWithTagName:@"span"];
+ [range surroundContents:span];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+}
+
+- (void)testSurroundContents_NonTextNodes
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"];
+ [range setStartNode:start startOffset:0];
+ HTMLNode *end = [document querySelector:@"#P1"];
+ [range setEndNode:end endOffset:2];
+
+ HTMLElement *span = [[HTMLElement alloc] initWithTagName:@"span"];
+ [range surroundContents:span];
+
+ XCTAssertEqualObjects(BodyOf(document), InnerHTML(
+ @""
+ @"
"
+ @"
World
"
+ @"
"
+ @"
"));
+}
+
+#pragma mark - Stringifier
+
+- (void)testRangeStringifier
+{
+ HTMLDocument *document = self.editingDocument;
+ HTMLRange *range = [[HTMLRange alloc] initWithDowcument:document];
+
+ HTMLNode *start = [document querySelector:@"#P1"].firstChild;
+ [range setStartNode:start startOffset:2];
+ HTMLNode *end = [document querySelector:@"#P1"].lastChild;
+ [range setEndNode:end endOffset:3];
+ XCTAssertEqualObjects([range textContent], @"is is a te");
+
+ start = [document querySelector:@"#P1"];
+ [range setStartNode:start startOffset:0];
+ end = [document querySelector:@"#P1"];
+ [range setEndNode:end endOffset:2];
+ XCTAssertEqualObjects([range textContent], @"This is a");
+
+ start = [document querySelector:@"#D1"];
+ [range setStartNode:start startOffset:0];
+ end = [document querySelector:@"#D1"];
+ [range setEndNode:end endOffset:1];
+ XCTAssertEqualObjects([range textContent], @"This is a text");
+
+ start = [document querySelector:@"#D1"];
+ [range setStartNode:start startOffset:0];
+ end = [document querySelector:@"#D1"];
+ [range setEndNode:end endOffset:2];
+ XCTAssertEqualObjects([range textContent], @"This is a textHello");
+
+ start = [document querySelector:@"#D1"];
+ [range setStartNode:start startOffset:0];
+ end = [document querySelector:@"#D2"];
+ [range setEndNode:end endOffset:0];
+ XCTAssertEqualObjects([range textContent], @"This is a textHelloWorld");
+
+ start = [document querySelector:@"#D1"];
+ [range setStartNode:start startOffset:0];
+ end = [document querySelector:@"#D2"];
+ [range setEndNode:end endOffset:1];
+ XCTAssertEqualObjects([range textContent], @"This is a textHelloWorldAnother text");
+}
+
+@end
diff --git a/Tests/HTMLKitStringCategoryTests.m b/Tests/HTMLStringCategoryTests.m
similarity index 100%
rename from Tests/HTMLKitStringCategoryTests.m
rename to Tests/HTMLStringCategoryTests.m
diff --git a/Tests/html5lib-tests b/Tests/html5lib-tests
index c305da7..50568b5 160000
--- a/Tests/html5lib-tests
+++ b/Tests/html5lib-tests
@@ -1 +1 @@
-Subproject commit c305da74fae50fb018870de7a042da36c1a93b65
+Subproject commit 50568b5664d6b034b752310603b2b664d045ad0f