diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj
index 4439f3b..f1bfc2c 100644
--- a/HTMLKit.xcodeproj/project.pbxproj
+++ b/HTMLKit.xcodeproj/project.pbxproj
@@ -317,6 +317,9 @@
62D91C281DE218A500BEFADE /* HTMLRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D91C221DE218A500BEFADE /* HTMLRange.m */; };
62D91C291DE218A500BEFADE /* HTMLRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D91C221DE218A500BEFADE /* HTMLRange.m */; };
62D91C2A1DE218A500BEFADE /* HTMLRange.m in Sources */ = {isa = PBXBuildFile; fileRef = 62D91C221DE218A500BEFADE /* HTMLRange.m */; };
+ 62E0BA971E25456700E4D193 /* HTMLCharacterDataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62E0BA961E25456700E4D193 /* HTMLCharacterDataTests.m */; };
+ 62E0BA981E25456700E4D193 /* HTMLCharacterDataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62E0BA961E25456700E4D193 /* HTMLCharacterDataTests.m */; };
+ 62E0BA991E25456700E4D193 /* HTMLCharacterDataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62E0BA961E25456700E4D193 /* HTMLCharacterDataTests.m */; };
62EC0A851E158BD80007786B /* HTMLRangeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC0A841E158BD80007786B /* HTMLRangeTests.m */; };
62EC0A861E158BD80007786B /* HTMLRangeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC0A841E158BD80007786B /* HTMLRangeTests.m */; };
62EC0A871E158BD80007786B /* HTMLRangeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 62EC0A841E158BD80007786B /* HTMLRangeTests.m */; };
@@ -718,6 +721,7 @@
62D8345819FB1AC4009205A9 /* HTML5LibTokenizerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTML5LibTokenizerTest.m; sourceTree = ""; };
62D91C211DE218A500BEFADE /* HTMLRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLRange.h; sourceTree = ""; };
62D91C221DE218A500BEFADE /* HTMLRange.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLRange.m; sourceTree = ""; };
+ 62E0BA961E25456700E4D193 /* HTMLCharacterDataTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLCharacterDataTests.m; sourceTree = ""; };
62E7CAAE19CDFFB500465A83 /* HTMLTokenizerCharacters.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = HTMLTokenizerCharacters.h; path = include/HTMLTokenizerCharacters.h; sourceTree = ""; };
62EC0A841E158BD80007786B /* HTMLRangeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLRangeTests.m; sourceTree = ""; };
62EC7AE51AEEAC6F0015D3BE /* HTMLMutationAlgorithmsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLMutationAlgorithmsTests.m; sourceTree = ""; };
@@ -881,6 +885,7 @@
624FC3791AE591D80015DDF9 /* HTMLNodesTests.m */,
62EC7AE51AEEAC6F0015D3BE /* HTMLMutationAlgorithmsTests.m */,
62EC0A841E158BD80007786B /* HTMLRangeTests.m */,
+ 62E0BA961E25456700E4D193 /* HTMLCharacterDataTests.m */,
);
name = DOM;
sourceTree = "";
@@ -1742,6 +1747,7 @@
buildActionMask = 2147483647;
files = (
62EC0A851E158BD80007786B /* HTMLRangeTests.m in Sources */,
+ 62E0BA971E25456700E4D193 /* HTMLCharacterDataTests.m in Sources */,
6216ACFD1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m in Sources */,
62132E5A1C01F83200084175 /* CSSSelectorTest.m in Sources */,
6239755B1AC362CA007E26F1 /* HTMLKitTreeConstructionTests.m in Sources */,
@@ -1883,6 +1889,7 @@
buildActionMask = 2147483647;
files = (
62EC0A871E158BD80007786B /* HTMLRangeTests.m in Sources */,
+ 62E0BA991E25456700E4D193 /* HTMLCharacterDataTests.m in Sources */,
62857D3B1D39A345008DC254 /* CSSSelectorTest.m in Sources */,
62857D421D39A345008DC254 /* CSSCombinatorSelectorTests.m in Sources */,
62857D3C1D39A345008DC254 /* CSSSelectorParserTests.m in Sources */,
@@ -1969,6 +1976,7 @@
buildActionMask = 2147483647;
files = (
62EC0A861E158BD80007786B /* HTMLRangeTests.m in Sources */,
+ 62E0BA981E25456700E4D193 /* HTMLCharacterDataTests.m in Sources */,
6216ACFE1C28DCC80074CAB4 /* CSSExtensionSelectorsParsingTests.m in Sources */,
62ECBFCA1C0B6E2E00AF847B /* HTML5LibTokenizerTest.m in Sources */,
62ECBFCB1C0B6E2E00AF847B /* HTMLKitTokenizerTests.m in Sources */,
diff --git a/Tests/HTMLCharacterDataTests.m b/Tests/HTMLCharacterDataTests.m
new file mode 100644
index 0000000..9d66891
--- /dev/null
+++ b/Tests/HTMLCharacterDataTests.m
@@ -0,0 +1,100 @@
+//
+// HTMLCharacterDataTests.m
+// HTMLKit
+//
+// Created by Iska on 10/01/17.
+// Copyright © 2017 BrainCookie. All rights reserved.
+//
+
+#import
+#import "HTMLElement.h"
+#import "HTMLCharacterData.h"
+#import "HTMLText.h"
+
+@interface HTMLCharacterDataTests : XCTestCase
+
+@end
+
+@implementation HTMLCharacterDataTests
+
+- (void)testSetData
+{
+ HTMLText *text = [[HTMLText alloc] initWithData:@"This is a text"];
+
+ [text setData:@"New text"];
+ XCTAssertEqualObjects(text.data, @"New text");
+}
+
+- (void)testAppendData
+{
+ HTMLText *text = [[HTMLText alloc] initWithData:@"This is a text"];
+
+ [text appendData:@"New text"];
+ XCTAssertEqualObjects(text.data, @"This is a textNew text");
+}
+
+- (void)testReplaceData
+{
+ HTMLText *text = [[HTMLText alloc] initWithData:@"This is a text"];
+
+ [text replaceDataInRange:NSMakeRange(0, 5) withData:@"New text "];
+ XCTAssertEqualObjects(text.data, @"New text is a text");
+
+ [text replaceDataInRange:NSMakeRange(4, 4) withData:@"data"];
+ XCTAssertEqualObjects(text.data, @"New data is a text");
+}
+
+- (void)testDeleteData
+{
+ HTMLText *text = [[HTMLText alloc] initWithData:@"This is a text"];
+
+ [text deleteDataInRange:NSMakeRange(5, 3)];
+ XCTAssertEqualObjects(text.data, @"This a text");
+
+ [text deleteDataInRange:NSMakeRange(0, text.data.length)];
+ XCTAssertEqualObjects(text.data, @"");
+}
+
+- (void)testInsertData
+{
+ HTMLText *text = [[HTMLText alloc] initWithData:@"This is a text"];
+
+ [text insertData:@"New " atOffset:10];
+ XCTAssertEqualObjects(text.data, @"This is a New text");
+
+ [text insertData:@"Prefix " atOffset:0];
+ XCTAssertEqualObjects(text.data, @"Prefix This is a New text");
+}
+
+- (void)testSplitText_Invalid
+{
+ HTMLText *text = [[HTMLText alloc] initWithData:@"text"];
+ XCTAssertThrows([text splitTextAtOffset:5]);
+}
+
+- (void)testSplitText
+{
+ HTMLElement *div = [[HTMLElement alloc] initWithTagName:@"div"];
+ HTMLText *text = [[HTMLText alloc] initWithData:@"This is a text"];
+ [div appendNode:text];
+
+ HTMLText *newText = [text splitTextAtOffset:7];
+ XCTAssertEqualObjects(newText.data, @" a text");
+
+ XCTAssertEqual(div.childNodesCount, 2);
+ XCTAssertEqualObjects(div.firstChild.textContent, @"This is");
+ XCTAssertEqualObjects(div.lastChild.textContent, @" a text");
+
+ [div appendNode:[[HTMLElement alloc] initWithTagName:@"p"]];
+
+ newText = [newText splitTextAtOffset:0];
+ XCTAssertEqualObjects(newText.data, @" a text");
+
+ XCTAssertEqual(div.childNodesCount, 4);
+ XCTAssertEqualObjects([div childNodeAtIndex:0].textContent, @"This is");
+ XCTAssertEqualObjects([div childNodeAtIndex:1].textContent, @"");
+ XCTAssertEqualObjects([div childNodeAtIndex:2].textContent, @" a text");
+ XCTAssertEqual([div childNodeAtIndex:3].nodeType, HTMLNodeElement);
+}
+
+@end