//
//  XTOutputTextParserTests.m
//  TadsTerp
//
//  Created by Rune Berg on 09/04/14.
//  Copyright (c) 2014 Rune Berg. All rights reserved.
//

#import <XCTest/XCTest.h>
#import "XTOutputTextParserHtml.h"
#import "XTHtmlTag.h"
#import "XTHtmlTagA.h"
#import "XTHtmlTagBr.h"
#import "XTHtmlTagTab.h"
#import "XTHtmlTagTitle.h"
#import "XTHtmlTagQ.h"
#import "XTHtmlTagB.h"
#import "XTHtmlTagQuestionMarkT2.h"
#import "XTHtmlTagCenter.h"
#import "XTHtmlTagWhitespace.h"
#import "XTHtmlTagQuotedSpace.h"
#import "XTHtmlTagNonbreakingSpace.h"
#import "XTHtmlTagSpecialSpace.h"
#import "XTHtmlTagNoop.h"
#import "XTHtmlTagP.h"
#import "XTHtmlTagI.h"
//#import "XTHtmlTagBq.h"
#import "XTHtmlTagFont.h"
#import "XTHtmlTagImg.h"
#import "XTHtmlTagBanner.h"
//#import "XTHtmlTagPseudoTest.h"
#import "XTPrefs.h"


@interface XTOutputTextParserHtmlTests : XCTestCase

@property XTOutputTextParserHtml *parser;

@end


#define ASSERT_PARSER_STATE(expectedState) \
	XCTAssertEqual(expectedState, self.parser.state);


@implementation XTOutputTextParserHtmlTests

- (void)setUp
{
    [super setUp];
	self.parser = [XTOutputTextParserHtml new];
}

- (void)tearDown
{
    [super tearDown];
}

/*TODO !!! adapt:
- (void)testEmptyInput_1
{
	NSArray *elements = [self.parser parse:@""];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	elements = [self.parser flush];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
}

- (void)testEmptyInput_2
{
	NSArray *elements = [self.parser parse:@""];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);

	elements = [self.parser parse:@""];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);

	elements = [self.parser parse:@""];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);

	elements = [self.parser flush];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
}

- (void)testOnlyRegularText_1
{
	NSArray *elements = [self.parser parse:@"a"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	[self assertRegularTextIn:elements[0] withValue:@"a"];
	
	elements = [self.parser parse:@"a>"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	[self assertRegularTextIn:elements[0] withValue:@"a>"];
	
	elements = [self.parser parse:@"abc"];
	XCTAssertEqual(0, elements.count);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"abc"];
}

- (void)testOnlyRegularText_2
{
	NSArray *elements = [self.parser parse:@"a"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	elements = [self.parser parse:@"b"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	elements = [self.parser parse:@"cd"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	[self assertRegularTextIn:elements[0] withValue:@"abcd"];
}

- (void)testOnlySingleWhitespaceChar
{
	NSArray *elements = [self.parser parse:@" "];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	[self assertWhitespaceIn:elements[0] withText:@" "];

	elements = [self.parser parse:@"\n"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	[self assertWhitespaceIn:elements[0] withText:@"\n"];
	
	elements = [self.parser parse:@"\t"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	[self assertWhitespaceIn:elements[0] withText:@"\t"];
}

- (void)testCollapsingWhitespaceChars_1
{
	NSArray *elements = [self.parser parse:@"  "];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	[self assertWhitespaceIn:elements[0] withText:@"  "];

	elements = [self.parser parse:@" "];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	[self assertWhitespaceIn:elements[0] withText:@" "];
	
	elements = [self.parser parse:@"    "];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	[self assertWhitespaceIn:elements[0] withText:@"    "];

	elements = [self.parser parse:@" \t"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	[self assertWhitespaceIn:elements[0] withText:@" \t"];
	
	elements = [self.parser parse:@"\t "];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	[self assertWhitespaceIn:elements[0] withText:@"\t "];
	
	elements = [self.parser parse:@" \n"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	[self assertWhitespaceIn:elements[0] withText:@" \n"];
	
	elements = [self.parser parse:@"\n \t"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	[self assertWhitespaceIn:elements[0] withText:@"\n \t"];
	
	elements = [self.parser parse:@"\n\n"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	[self assertWhitespaceIn:elements[0] withText:@"\n\n"];
	
	elements = [self.parser parse:@"\t\t"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	[self assertWhitespaceIn:elements[0] withText:@"\t\t"];
	
	elements = [self.parser parse:@" \n\t\n  \t "];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	[self assertWhitespaceIn:elements[0] withText:@" \n\t\n  \t "];
}

- (void)testCollapsingWhitespaceChars_2
{
	NSArray *elements = [self.parser parse:@" "];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser parse:@" "];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser parse:@"\t"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser parse:@"\n"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	[self assertWhitespaceIn:elements[0] withText:@"  \t\n"];
}

- (void)testMixOfTextAndWhitespace
{
	NSArray *elements = [self.parser parse:@"a "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@" "];
	
	elements = [self.parser parse:@" z"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@" "];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"z"];
	
	elements = [self.parser parse:@"zz b"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(2, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"zz"];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"b"];
	
	elements = [self.parser parse:@" cv  xy"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(3, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@" "];
	[self assertRegularTextIn:elements[1] withValue:@"cv"];
	[self assertWhitespaceIn:elements[2] withText:@"  "];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"xy"];
	
	elements = [self.parser parse:@"a bc  def  \nGG\th"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(8, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a"];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"bc"];
	[self assertWhitespaceIn:elements[3] withText:@"  "];
	[self assertRegularTextIn:elements[4] withValue:@"def"];
	[self assertWhitespaceIn:elements[5] withText:@"  \n"];
	[self assertRegularTextIn:elements[6] withValue:@"GG"];
	[self assertWhitespaceIn:elements[7] withText:@"\t"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"h"];
}

- (void)testXTHtmlNonbreakingSpace
{
	NSArray *elements;
	
	elements = [self.parser parse:@"&#160;"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertNonbreakingSpaceIn:elements[0]];
	
	elements = [self.parser parse:@"&#160;&nbsp;&#xA0;"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(3, elements.count);
	[self assertNonbreakingSpaceIn:elements[0]];
	[self assertNonbreakingSpaceIn:elements[1]];
	[self assertNonbreakingSpaceIn:elements[2]];
	
	elements = [self.parser parse:@"a&#160;b"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a"];
	[self assertNonbreakingSpaceIn:elements[1]];
	[self assertRegularTextIn:elements[2] withValue:@"b"];
}

- (void)testQuotedSpace
{
	NSArray *elements;
	
	elements = [self.parser parse:@"&#21;"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertQuotedSpaceIn:elements[0]];
	
	elements = [self.parser parse:@"&#21;&#21;&#21;"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(3, elements.count);
	[self assertQuotedSpaceIn:elements[0]];
	[self assertQuotedSpaceIn:elements[1]];
	[self assertQuotedSpaceIn:elements[2]];
	
	elements = [self.parser parse:@"a&#21;"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(2, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a"];
	[self assertQuotedSpaceIn:elements[1]];
	
	elements = [self.parser parse:@"&#21;a"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(2, elements.count);
	[self assertQuotedSpaceIn:elements[0]];
	[self assertRegularTextIn:elements[1] withValue:@"a"];
	
	elements = [self.parser parse:@"ab&#21;c"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	[self assertQuotedSpaceIn:elements[1]];
	[self assertRegularTextIn:elements[2] withValue:@"c"];
	
	elements = [self.parser parse:@"ab&#21;cd&#21;&#21;ef&#21;"];
	XCTAssertEqual(0, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(7, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	[self assertQuotedSpaceIn:elements[1]];
	[self assertRegularTextIn:elements[2] withValue:@"cd"];
	[self assertQuotedSpaceIn:elements[3]];
	[self assertQuotedSpaceIn:elements[4]];
	[self assertRegularTextIn:elements[5] withValue:@"ef"];
	[self assertQuotedSpaceIn:elements[6]];
	
	elements = [self.parser parse:@"&#21; "];
	XCTAssertEqual(1, elements.count);
	[self assertQuotedSpaceIn:elements[0]];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@" "];
	
	elements = [self.parser parse:@" &#21;"];
	XCTAssertEqual(1, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@" "];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertQuotedSpaceIn:elements[0]];
	
	elements = [self.parser parse:@"  &#21; "];
	XCTAssertEqual(2, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@"  "];
	[self assertQuotedSpaceIn:elements[1]];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@" "];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	
	elements = [self.parser parse:@" a  &#21;&#21; &#21;b &#21; "];
	XCTAssertEqual(10, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@" "];
	[self assertRegularTextIn:elements[1] withValue:@"a"];
	[self assertWhitespaceIn:elements[2] withText:@"  "];
	[self assertQuotedSpaceIn:elements[3]];
	[self assertQuotedSpaceIn:elements[4]];
	[self assertWhitespaceIn:elements[5] withText:@" "];
	[self assertQuotedSpaceIn:elements[6]];
	[self assertRegularTextIn:elements[7] withValue:@"b"];
	[self assertWhitespaceIn:elements[8] withText:@" "];
	[self assertQuotedSpaceIn:elements[9]];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@" "];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
}

- (void)testTypographicalSpaces_hex // unfortunately called "special spaced" in potions of code :-(
{
	NSArray *elements = [self.parser parse:@"\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a "];
	XCTAssertEqual(9, elements.count);
	[self assertSpecialSpaceIn:elements[0] withChar:0x2002];
	[self assertSpecialSpaceIn:elements[1] withChar:0x2003];
	[self assertSpecialSpaceIn:elements[2] withChar:0x2004];
	[self assertSpecialSpaceIn:elements[3] withChar:0x2005];
	[self assertSpecialSpaceIn:elements[4] withChar:0x2006];
	[self assertSpecialSpaceIn:elements[5] withChar:0x2007];
	[self assertSpecialSpaceIn:elements[6] withChar:0x2008];
	[self assertSpecialSpaceIn:elements[7] withChar:0x2009];
	[self assertSpecialSpaceIn:elements[8] withChar:0x200a];
}

- (void)testTypographicalSpaces_named
{
	NSArray *elements = [self.parser parse:@"&ensp;&emsp;&tpmsp;&fpmsp;&spmsp;&figsp;&puncsp;&thinsp;&hairsp; "];
	XCTAssertEqual(9, elements.count);
	[self assertSpecialSpaceIn:elements[0] withChar:0x2002];
	[self assertSpecialSpaceIn:elements[1] withChar:0x2003];
	[self assertSpecialSpaceIn:elements[2] withChar:0x2004];
	[self assertSpecialSpaceIn:elements[3] withChar:0x2005];
	[self assertSpecialSpaceIn:elements[4] withChar:0x2006];
	[self assertSpecialSpaceIn:elements[5] withChar:0x2007];
	[self assertSpecialSpaceIn:elements[6] withChar:0x2008];
	[self assertSpecialSpaceIn:elements[7] withChar:0x2009];
	[self assertSpecialSpaceIn:elements[8] withChar:0x200a];
}

- (void)testOnlyStandaloneTag
{
	NSArray *elements = [self.parser parse:@"<br>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTagTitle *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	elements = [self.parser flush];
	XCTAssertEqual(0, elements.count);

	elements = [self.parser parse:@"<BR>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	elements = [self.parser flush];
	XCTAssertEqual(0, elements.count);
	
	elements = [self.parser parse:@"<bR>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	elements = [self.parser flush];
	XCTAssertEqual(0, elements.count);
	
	elements = [self.parser parse:@"<bR >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	elements = [self.parser flush];
	XCTAssertEqual(0, elements.count);
	
	elements = [self.parser parse:@"<bR  >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	elements = [self.parser flush];
	XCTAssertEqual(0, elements.count);
	
	elements = [self.parser parse:@"</br>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	elements = [self.parser flush];
	XCTAssertEqual(0, elements.count);
	
	elements = [self.parser parse:@"</br >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	elements = [self.parser flush];
	XCTAssertEqual(0, elements.count);
	
	elements = [self.parser parse:@"<br/>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	elements = [self.parser flush];
	XCTAssertEqual(0, elements.count);
	
	elements = [self.parser parse:@"<br />"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	elements = [self.parser flush];
	XCTAssertEqual(0, elements.count);
	
	elements = [self.parser parse:@"<br/ >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	elements = [self.parser flush];
	XCTAssertEqual(0, elements.count);
	
	elements = [self.parser parse:@"<br / >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	elements = [self.parser flush];
	XCTAssertEqual(0, elements.count);
}

- (void)testStandaloneTagMixedWithRegularText
{
	NSArray *elements = [self.parser parse:@"abc<br>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(2, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"abc"];
	XTHtmlTagTitle *tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(0, elements.count);

	elements = [self.parser parse:@"<br>a"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a"];
}

- (void)testOnlyStandaloneTagWithSingleAttribute
{
	NSArray *elements = [self.parser parse:@"<br height=2>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTagBr *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqualObjects(@"2", [tag attributeAsString:@"height"]);
	XCTAssertEqual(2, [tag attributeAsUInt:@"height"]);
	XCTAssertFalse(tag.closing);

	elements = [self.parser parse:@"<br HEIGHT=2>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqualObjects(@"2", [tag attributeAsString:@"height"]);
	XCTAssertEqual(2, [tag attributeAsUInt:@"height"]);
	XCTAssertFalse(tag.closing);
	
	elements = [self.parser parse:@"<br HEIghT=2>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqualObjects(@"2", [tag attributeAsString:@"HEIGHT"]);
	XCTAssertEqual(2, [tag attributeAsUInt:@"hEIght"]);
	XCTAssertFalse(tag.closing);

	elements = [self.parser parse:@"<BR HEIGHT=0>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqualObjects(@"0", [tag attributeAsString:@"HEIGHT"]);
	XCTAssertEqual(0, [tag attributeAsUInt:@"HEIGHT"]);
	XCTAssertFalse(tag.closing);

	elements = [self.parser parse:@"<BR HEIGHT=>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"HEIGHT"]);
	XCTAssertEqual(0, [tag attributeAsUInt:@"HEIGHT"]);
	XCTAssertFalse(tag.closing);
	
	elements = [self.parser parse:@"<BR HEIGHT=/>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"HEIGHT"]);
	XCTAssertEqual(0, [tag attributeAsUInt:@"HEIGHT"]);
	XCTAssertFalse(tag.closing);
	
	elements = [self.parser parse:@"<BR HEIGHT= />"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"HEIGHT"]);
	XCTAssertEqual(0, [tag attributeAsUInt:@"HEIGHT"]);
	XCTAssertFalse(tag.closing);
	
	elements = [self.parser parse:@"<BR HEIGHT=/ >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"HEIGHT"]);
	XCTAssertEqual(0, [tag attributeAsUInt:@"HEIGHT"]);
	XCTAssertFalse(tag.closing);
	
	elements = [self.parser parse:@"<BR HEIGHT=\\>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"HEIGHT"]);
	XCTAssertEqual(0, [tag attributeAsUInt:@"HEIGHT"]);
	XCTAssertFalse(tag.closing);
	
	elements = [self.parser parse:@"<BR HEIGHT=2 />"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqualObjects(@"2", [tag attributeAsString:@"HEIGHT"]);
	XCTAssertEqual(2, [tag attributeAsUInt:@"HEIGHT"]);
	XCTAssertFalse(tag.closing);
	
	elements = [self.parser parse:@"<BR HEIGHT=3 / >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqualObjects(@"3", [tag attributeAsString:@"HEIGHT"]);
	XCTAssertEqual(3, [tag attributeAsUInt:@"HEIGHT"]);
	XCTAssertFalse(tag.closing);
	
	elements = [self.parser parse:@"<BR HEIGHT=7 \\>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqualObjects(@"7", [tag attributeAsString:@"HEIGHT"]);
	XCTAssertEqual(7, [tag attributeAsUInt:@"HEIGHT"]);
	XCTAssertFalse(tag.closing);
	
	elements = [self.parser parse:@"<BR HEIGHT=0 />"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqualObjects(@"0", [tag attributeAsString:@"HEIGHT"]);
	XCTAssertEqual(0, [tag attributeAsUInt:@"HEIGHT"]);
	XCTAssertFalse(tag.closing);
	
	elements = [self.parser parse:@"<BR HEIGHT=0 \\>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqualObjects(@"0", [tag attributeAsString:@"HEIGHT"]);
	XCTAssertEqual(0, [tag attributeAsUInt:@"HEIGHT"]);
	XCTAssertFalse(tag.closing);
	
	elements = [self.parser parse:@"<BR HEIGHT=5 \\ >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqualObjects(@"5", [tag attributeAsString:@"HEIGHT"]);
	XCTAssertEqual(5, [tag attributeAsUInt:@"HEIGHT"]);
	XCTAssertFalse(tag.closing);
}

//-------- Test HTML attribute handling ----------

- (void)testEmptyAttributes
{
	NSArray *elements = [self.parser parse:@"<font size>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"size"]);

	elements = [self.parser parse:@"<font size/>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"size"]);
	
	elements = [self.parser parse:@"<font size />"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"size"]);
	
	elements = [self.parser parse:@"<font size/ >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"size"]);
	
	elements = [self.parser parse:@"<font size / >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"size"]);

	elements = [self.parser parse:@"<font size\\>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"size"]);
	
	elements = [self.parser parse:@"<font size \\>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"size"]);
	
	elements = [self.parser parse:@"<font size\\ >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"size"]);
	
	elements = [self.parser parse:@"<font size \\ >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"size"]);
	
	elements = [self.parser parse:@"<font size color=>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(2, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"size"]);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"color"]);
	
	elements = [self.parser parse:@"<font size color= bgcolor= >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(3, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"size"]);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"color"]);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"bgcolor"]);
	
	elements = [self.parser parse:@"<font size=2 size=3>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"3", [tag attributeAsString:@"size"]);
	
	elements = [self.parser parse:@"<font size=2 size=  >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"size"]);
	
	elements = [self.parser parse:@"<font size=2 color=>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(2, tag.attributes.count);
	XCTAssertEqualObjects(@"2", [tag attributeAsString:@"size"]);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"color"]);
	
	elements = [self.parser parse:@"<font size=2 color>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(2, tag.attributes.count);
	XCTAssertEqualObjects(@"2", [tag attributeAsString:@"size"]);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"color"]);
	
	elements = [self.parser parse:@"<font size=2 color >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(2, tag.attributes.count);
	XCTAssertEqualObjects(@"2", [tag attributeAsString:@"size"]);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"color"]);
	
	elements = [self.parser parse:@"<font size color=green >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(2, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"size"]);
	XCTAssertEqualObjects(@"green", [tag attributeAsString:@"coLOR"]);
}

- (void)testUnquotedAttributes
{
	NSArray *elements = [self.parser parse:@"<font size=6>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"6", [tag attributeAsString:@"size"]);

	elements = [self.parser parse:@"<font size=+5 bgcolor=white color=green>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(3, tag.attributes.count);
	XCTAssertEqualObjects(@"+5", [tag attributeAsString:@"size"]);
	XCTAssertEqualObjects(@"white", [tag attributeAsString:@"bgcolor"]);
	XCTAssertEqualObjects(@"green", [tag attributeAsString:@"color"]);
}

- (void)testUnquotedAttributeValueWithForwardSlash
{
	[self turnOffBrokenHtmlOutput];
	
	NSArray *elements = [self.parser parse:@"<img src=../image.gif>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagImg class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"../image.gif", [tag attributeAsString:@"src"]);

	elements = [self.parser parse:@"<img src=..\\image.gif>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagImg class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"..\\image.gif", [tag attributeAsString:@"src"]);
	
	elements = [self.parser parse:@"<img src=../image.gif/>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagImg class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"../image.gif/", [tag attributeAsString:@"src"]);
}

- (void)testUnquotedAttributeValue_error_closing
{
	NSArray *elements = [self.parser parse:@"m</p w== mu>pp  "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"m"];
	XTHtmlTagBr *tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagP class]];
	XCTAssertEqual(2, tag.attributes.count);
	XCTAssertTrue(tag.closing);
	[self assertRegularTextIn:elements[2] withValue:@"pp"];
	[self.parser resetForNextCommand];
}

- (void)testSingleQuotedAttribute_1
{
	NSArray *elements = [self.parser parse:@"<br height='2'>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTagBr *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"2", [tag attributeAsString:@"height"]);
	XCTAssertEqual(2, [tag attributeAsUInt:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];

	elements = [self.parser parse:@"<br HEIGHT=''>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"<br HEIGHT=' '>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@" ", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"<br HEIGHT=' 2 '>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@" 2 ", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"<br HEIGHT='\"23\"'>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"\"23\"", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"<br HEIGHT='\"'>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"\"", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"<br HEIGHT='\"\"'>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"\"\"", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"<br HEIGHT='\"\"' muups='98'>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(2, tag.attributes.count);
	XCTAssertEqualObjects(@"\"\"", [tag attributeAsString:@"height"]);
	XCTAssertEqualObjects(@"98", [tag attributeAsString:@"muups"]);
	XCTAssertFalse(tag.closing);
}

- (void)testSingleQuotedAttribute_2
	{
	//test "/" and "/>" inside single quotes:
	
	NSArray *elements = [self.parser parse:@"<br HEIGHT='/'>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"/", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
	}

- (void)testSingleQuotedAttribute_3
{
	NSArray *elements = [self.parser parse:@"<br HEIGHT='>'>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@">", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"<br HEIGHT='/>'>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"/>", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
}

- (void)testSingleQuotedAttribute_4
{
	NSArray *elements = [self.parser parse:@"xy<br>a<br HEIGHT='4>'b"];
	ASSERT_PARSER_STATE(XT_HTML_IN_ATTRIBUTE_NAME);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"xy"];
	XTHtmlTag *tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[2] withValue:@"a"];
	[self.parser resetForNextCommand];
	/ *TODO rm:
	tag = elements[3];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"4", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	* /
	
	elements = [self.parser parse:@"xy<br>a<\b HEIGHT='4>'b "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(4, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"xy"];
	tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[2] withValue:@"a"];
	[self assertRegularTextIn:elements[3] withValue:@"'b"];
	[self.parser resetForNextCommand];
}

- (void)testSingleQuotedAttribute_4b
{
	NSArray *elements = [self.parser parse:@"xy<br><b>a<\\b HEIGHT='4>'b "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(6, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"xy"];
	XTHtmlTag *tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	tag = elements[2];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertFalse(tag.closing);
	XCTAssertEqual(0, tag.attributes.count);
	[self assertRegularTextIn:elements[3] withValue:@"a"];
	tag = elements[4];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertTrue(tag.closing);
	[self assertRegularTextIn:elements[5] withValue:@"'b"];
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"xy<br><b>a<b HEIGHT='4>'b "];
	ASSERT_PARSER_STATE(XT_HTML_AFTER_TAG_NAME);
	XCTAssertEqual(4, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"xy"];
	tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	tag = elements[2];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertFalse(tag.closing);
	XCTAssertEqual(0, tag.attributes.count);
	[self assertRegularTextIn:elements[3] withValue:@"a"];
	[self.parser resetForNextCommand];
	/ *TODO rm
	tag = elements[4];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertFalse(tag.closing);
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"4", [tag attributeAsString:@"height"]);
	[self.parser resetForNextCommand];
	* /
	
	elements = [self.parser parse:@"xy<br><b>a</b HEIGHT='4>'b "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(6, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"xy"];
	tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	tag = elements[2];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertFalse(tag.closing);
	XCTAssertEqual(0, tag.attributes.count);
	[self assertRegularTextIn:elements[3] withValue:@"a"];
	tag = elements[4];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertTrue(tag.closing);
	[self assertRegularTextIn:elements[5] withValue:@"'b"];
	[self.parser resetForNextCommand];
}

- (void)testSingleQuotedAttribute_5
{
	NSArray *elements = [self.parser parse:@"a<br HEIGHT='/>'>b "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a"];
	XTHtmlTag *tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	XCTAssertEqualObjects(@"/>", [tag attributeAsString:@"height"]);
	[self assertRegularTextIn:elements[2] withValue:@"b"];
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"<br HEIGHT='/>'>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	XCTAssertEqualObjects(@"/>", [tag attributeAsString:@"height"]);
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"<br HEIGHT='>'>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	XCTAssertEqualObjects(@">", [tag attributeAsString:@"height"]);
	[self.parser resetForNextCommand];

	elements = [self.parser parse:@"</br HEIGHT='>'> "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(2, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertTrue(tag.closing);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"height"]);
	[self assertRegularTextIn:elements[1] withValue:@"'>"];
	[self.parser resetForNextCommand];

	elements = [self.parser parse:@"a</br HEIGHT='>'>b "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a"];
	tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertTrue(tag.closing);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"height"]);
	[self assertRegularTextIn:elements[2] withValue:@"'>b"];
	[self.parser resetForNextCommand];
}

- (void)testSingleQuotedAttribute_6
{
	NSArray *elements = [self.parser parse:@"xy<br>a<br HEIGHT='4>'>b "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(5, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"xy"];
	XTHtmlTag *tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[2] withValue:@"a"];
	tag = elements[3];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"4>", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[4] withValue:@"b"];
	[self.parser resetForNextCommand];
}

- (void)testDoubleQuotedAttribute
{
	NSArray *elements = [self.parser parse:@"<br height=\"2\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTagBr *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"2", [tag attributeAsString:@"height"]);
	XCTAssertEqual(2, [tag attributeAsUInt:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];

	elements = [self.parser parse:@"<br HEIGHT=\"\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];

	elements = [self.parser parse:@"<br HEIGHT=\"  \">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"  ", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"<br HEIGHT=\" 2 \">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@" 2 ", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"<br HEIGHT=\"'23'\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"'23'", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"<br HEIGHT=\"'\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"'", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"<br HEIGHT=\"''\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"''", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];

	// test "/" and "/>" inside double quotes:
	
	elements = [self.parser parse:@"<br HEIGHT=\"/\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"/", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"<br HEIGHT=\">\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@">", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
	
	elements = [self.parser parse:@"<br HEIGHT=\"/>\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"/>", [tag attributeAsString:@"height"]);
	XCTAssertFalse(tag.closing);
	[self.parser resetForNextCommand];
}

- (void)testCharEntitiesInAttribute
{
	NSArray *elements = [self.parser parse:@"<font size=+&#51;>+3</font>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"+3", [tag attributeAsString:@"size"]);
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[1] withValue:@"+3"];
	tag = elements[2];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertTrue(tag.closing);
	XCTAssertEqual(0, tag.attributes.count);
	[self.parser resetForNextCommand];

	elements = [self.parser parse:@"<font size='&#43;&#51;'>+3</font>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqualObjects(@"+3", [tag attributeAsString:@"size"]);
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[1] withValue:@"+3"];
	tag = elements[2];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertTrue(tag.closing);
	[self.parser resetForNextCommand];

	elements = [self.parser parse:@"<font size=\"+&#51;\">&#43;3</font>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqualObjects(@"+3", [tag attributeAsString:@"size"]);
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[1] withValue:@"+3"];
	tag = elements[2];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertTrue(tag.closing);
	[self.parser resetForNextCommand];

	elements = [self.parser parse:@"<font size='+&#51;' mii=\"&#51;&#51;\" zzk=&#51;>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class] closing:NO];
	XCTAssertEqualObjects(@"+3", [tag attributeAsString:@"size"]);
	XCTAssertEqualObjects(@"33", [tag attributeAsString:@"mii"]);
	XCTAssertEqualObjects(@"3", [tag attributeAsString:@"zzk"]);
	[self.parser resetForNextCommand];
}

//----------- Test ???? --------------

- (void)testWhitespaceAfterOpeningTag
{
	NSArray *elements = [self.parser parse:@"<br> ab c<b>de "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(7, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagBr class]];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"ab"];
	[self assertWhitespaceIn:elements[3] withText:@" "];
	[self assertRegularTextIn:elements[4] withValue:@"c"];
	[self assertHtmlTagIn:elements[5] withClass:[XTHtmlTagB class]];
	[self assertRegularTextIn:elements[6] withValue:@"de"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@" "];

	elements = [self.parser parse:@"<br height=2> ab c <br height=\"2\">  de "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(9, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagBr class]];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"ab"];
	[self assertWhitespaceIn:elements[3] withText:@" "];
	[self assertRegularTextIn:elements[4] withValue:@"c"];
	[self assertWhitespaceIn:elements[5] withText:@" "];
	[self assertHtmlTagIn:elements[6] withClass:[XTHtmlTagBr class]];
	[self assertWhitespaceIn:elements[7] withText:@"  "];
	[self assertRegularTextIn:elements[8] withValue:@"de"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@" "];
}

- (void)testWhitespaceAfterClosingTag
{
	NSArray *elements = [self.parser parse:@"<b> ab c</b> de "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(8, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagB class]];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"ab"];
	[self assertWhitespaceIn:elements[3] withText:@" "];
	[self assertRegularTextIn:elements[4] withValue:@"c"];
	[self assertHtmlTagIn:elements[5] withClass:[XTHtmlTagB class]];
	[self assertWhitespaceIn:elements[6] withText:@" "];
	[self assertRegularTextIn:elements[7] withValue:@"de"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@" "];

	elements = [self.parser parse:@"ab<br/>   cd"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	[self assertHtmlTagIn:elements[1] withClass:[XTHtmlTagBr class]];
	[self assertWhitespaceIn:elements[2] withText:@"   "];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"cd"];
}

- (void)testWhitespaceAfterClosingTagWhenUnknownTag
{
	[self turnOnBrokenHtmlOutput];
	NSArray *elements = [self.parser parse:@"Please type <uu href=Help>HELP</uu> for instructions"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(10, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"Please"];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"type"];
	[self assertWhitespaceIn:elements[3] withText:@" "];
	[self assertRegularTextIn:elements[4] withValue:@"<uu href=Help>"];
	[self assertRegularTextIn:elements[5] withValue:@"HELP"];
	[self assertRegularTextIn:elements[6] withValue:@"</uu>"];
	[self assertWhitespaceIn:elements[7] withText:@" "];
	[self assertRegularTextIn:elements[8] withValue:@"for"];
	[self assertWhitespaceIn:elements[9] withText:@" "];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"instructions"];
	[self.parser resetForNextCommand];

	[self turnOffBrokenHtmlOutput];
	elements = [self.parser parse:@"Please type <uu href=Help>HELP</uu> for instructions"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(8, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"Please"];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"type"];
	[self assertWhitespaceIn:elements[3] withText:@" "];
	[self assertRegularTextIn:elements[4] withValue:@"HELP"];
	[self assertWhitespaceIn:elements[5] withText:@" "];
	[self assertRegularTextIn:elements[6] withValue:@"for"];
	[self assertWhitespaceIn:elements[7] withText:@" "];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"instructions"];
}

- (void)testOpenTag
{
	NSArray *elements = [self.parser parse:@"<i>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagI class] closing:NO];
	
	elements = [self.parser parse:@"<bq>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagBq class] closing:NO];
	
	elements = [self.parser parse:@"<bq >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagBq class] closing:NO];
}

- (void)testCloseTag
{
	NSArray *elements = [self.parser parse:@"</bq>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagBq class] closing:YES];
	
	elements = [self.parser parse:@"</bq >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagBq class] closing:YES];
	
	elements = [self.parser parse:@"<\\bq>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagBq class] closing:YES];
	
	elements = [self.parser parse:@"<\\bq >"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagBq class] closing:YES];
}

//-------- Test incomplete entity in attribute

- (void)testIncompleteEntitiyInAttribute1 // complete entity, for ref.
{
	NSArray *elements = [self.parser parse:@"<a href=\"&amp;\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"&", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute2
{
	NSArray *elements = [self.parser parse:@"<a href=\"&amp\">"]; 
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"&", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute2b
{
	NSArray *elements = [self.parser parse:@"<a href=\"&amp \">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"& ", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute3
{
	NSArray *elements = [self.parser parse:@"<a href=\"&am\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"&am", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute3b
{
	NSArray *elements = [self.parser parse:@"<a href=\"&am \">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"&am ", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute4
{
	NSArray *elements = [self.parser parse:@"<a href=\"&\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"&", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute4b
{
	NSArray *elements = [self.parser parse:@"<a href=\"& \">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"& ", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute4c
{
	NSArray *elements = [self.parser parse:@"<a href=\"&\">text</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, ((XTHtmlTag *)elements[0]).attributes.count);
	XCTAssertEqualObjects(@"&", [elements[0] attributeAsString:@"href"]);
	[self assertRegularTextIn:elements[1] withValue:@"text"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)testIncompleteEntitiyInAttribute5 // .. for ref.
{
	NSArray *elements = [self.parser parse:@"<a href=\"&#65;\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"A", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute6
{
	NSArray *elements = [self.parser parse:@"<a href=\"&#65\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"A", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute6b
{
	NSArray *elements = [self.parser parse:@"<a href=\"&#65 \">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"A ", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute7
{
	NSArray *elements = [self.parser parse:@"<a href=\"&#6\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"\6", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute8
{
	NSArray *elements = [self.parser parse:@"<a href=\"&#\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"&#", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute8b
{
	NSArray *elements = [self.parser parse:@"<a href=\"&# \">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"&# ", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute9 // .. for ref.
{
	NSArray *elements = [self.parser parse:@"<a href=\"&#x41;\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"A", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute10
{
	NSArray *elements = [self.parser parse:@"<a href=\"&#x41\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"A", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute11
{
	NSArray *elements = [self.parser parse:@"<a href=\"&#x4\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"\4", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute11b
{
	NSArray *elements = [self.parser parse:@"<a href=\"&#x4 \">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"\4 ", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute12
{
	NSArray *elements = [self.parser parse:@"<a href=\"&#x\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"&#x", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute12b
{
	NSArray *elements = [self.parser parse:@"<a href=\"&#x  \">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"&#x  ", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute12c
{
	NSArray *elements = [self.parser parse:@"<a href=\"b&#x\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"b&#x", [tag attributeAsString:@"href"]);
}

- (void)testIncompleteEntitiyInAttribute13
{
	NSArray *elements = [self.parser parse:@"<a href=\"&# \">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagA class] closing:NO];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"&# ", [tag attributeAsString:@"href"]);
}

//TODO test complete but unknown named entity in attr

//-------- Incomplete entity between tags

- (void)testIncompleteEntitiyBetweenTags0 // ...for ref.
{
	NSArray *elements = [self.parser parse:@"<a>&amp;</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"&"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)testIncompleteEntitiyBetweenTags1
{
	NSArray *elements = [self.parser parse:@"<a>&amp</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"&"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)testIncompleteEntitiyBetweenTags2
{
	NSArray *elements = [self.parser parse:@"<a>&am</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"&am"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)testIncompleteEntitiyBetweenTags3
{
	NSArray *elements = [self.parser parse:@"<a>&a</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"&a"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)testIncompleteEntitiyBetweenTags3b
{
	NSArray *elements = [self.parser parse:@"<a>B&a</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(4, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"B"];
	[self assertRegularTextIn:elements[2] withValue:@"&a"];
	[self assertHtmlTagIn:elements[3] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)testIncompleteEntitiyBetweenTags4
{
	NSArray *elements = [self.parser parse:@"<a>&</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"&"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)testIncompleteEntitiyBetweenTags5 // ... for ref
{
	NSArray *elements = [self.parser parse:@"<a>&#65;</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"A"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)testIncompleteEntitiyBetweenTags6
{
	NSArray *elements = [self.parser parse:@"<a>&#65</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"A"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)testIncompleteEntitiyBetweenTags7
{
	NSArray *elements = [self.parser parse:@"<a>&#6</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"\6"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)testIncompleteEntitiyBetweenTags8
{
	NSArray *elements = [self.parser parse:@"<a>&#</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"&#"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)testIncompleteEntitiyBetweenTags9 // ... for ref.
{
	NSArray *elements = [self.parser parse:@"<a>&#x41;</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"A"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)testIncompleteEntitiyBetweenTags10
{
	NSArray *elements = [self.parser parse:@"<a>&#x41</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"A"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)testIncompleteEntitiyBetweenTags10b
{
	NSArray *elements = [self.parser parse:@"<a>Z&#x41</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(4, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"Z"];
	[self assertRegularTextIn:elements[2] withValue:@"A"];
	[self assertHtmlTagIn:elements[3] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)testIncompleteEntitiyBetweenTags11
{
	NSArray *elements = [self.parser parse:@"<a>&#x4</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"\4"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)testIncompleteEntitiyBetweenTags12
{
	NSArray *elements = [self.parser parse:@"<a>&#x</a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"&#x"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class] closing:YES];
}

//------- Incomplete named/dec/hex entity in gen'l text -------

- (void)testIncompleteEntitiyInText0 // ... for ref.
{
	NSArray *elements = [self.parser parse:@"a&amp;b "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a&b"];
}

- (void)testIncompleteEntitiyInText1
{
	NSArray *elements = [self.parser parse:@"a&amp.b "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a&.b"];
}

- (void)testIncompleteEntitiyInText2
{
	NSArray *elements = [self.parser parse:@"a&am.b "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a&am.b"];
}

- (void)testIncompleteEntitiyInText3
{
	NSArray *elements = [self.parser parse:@"a&a.b "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a&a.b"];
}

- (void)testIncompleteEntitiyInText4
{
	NSArray *elements = [self.parser parse:@"a&.b "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a&.b"];
}

- (void)testIncompleteEntitiyInText5
{
	NSArray *elements = [self.parser parse:@"ab&amp;cd&amp.de&am.f&a.g&.h "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab&cd&.de&am.f&a.g&.h"];
}

- (void)testIncompleteEntitiyInText6
{
	NSArray *elements = [self.parser parse:@"ab&#65;cd&#65.de&#6.f&#.g&.h "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"abAcdA.de\6.f&#.g&.h"];
}

- (void)testIncompleteEntitiyInText7
{
	NSArray *elements = [self.parser parse:@"&amp;&amp&am&a& "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(2, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"&&&am&a"];
	[self assertRegularTextIn:elements[1] withValue:@"&"];
}

- (void)testIncompleteEntityInTextBeforeFlush1
{
	NSArray *elements = [self.parser parse:@"ab&am"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(0, elements.count);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	elements = [self.parser parse:@"p;c "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"&c"];
}

- (void)testIncompleteEntityInTextBeforeFlush2
{
	NSArray *elements = [self.parser parse:@"ab&a"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(0, elements.count);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	elements = [self.parser parse:@" c "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"&a"];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"c"];
}

- (void)testIncompleteEntityInTextBeforeFlush3
{
	NSArray *elements = [self.parser parse:@"ab&a"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(0, elements.count);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	elements = [self.parser parse:@"<b>bold "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"&a"];
	[self assertHtmlTagIn:elements[1] withClass:[XTHtmlTagB class]];
	[self assertRegularTextIn:elements[2] withValue:@"bold"];
}

//------- Incomplete named/dec/hex entity after whitespace -------

- (void)testIncompleteEntityAfterWhitespace0 // ...for ref.
{
	NSArray *elements = [self.parser parse:@"ab &amp; "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"&"];
}

- (void)testIncompleteEntityAfterWhitespace1
{
	NSArray *elements = [self.parser parse:@"ab &amp "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"&"];
}

- (void)testIncompleteEntityAfterWhitespace2
{
	NSArray *elements = [self.parser parse:@"ab &am "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"&am"];
}

- (void)testIncompleteEntityAfterWhitespace3
{
	NSArray *elements = [self.parser parse:@"a &a "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a"];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"&a"];
}

- (void)testIncompleteEntityAfterWhitespace4
{
	NSArray *elements = [self.parser parse:@"a & "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a"];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"&"];
}

- (void)testIncompleteEntityAfterWhitespace5
{
	NSArray *elements = [self.parser parse:@"a && "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(4, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a"];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"&"];
	[self assertRegularTextIn:elements[3] withValue:@"&"];
}

- (void)testIncompleteEntityAfterWhitespace6 // ...for ref.
{
	NSArray *elements = [self.parser parse:@"ab &#65; "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"A"];
}

- (void)testIncompleteEntityAfterWhitespace7
{
	NSArray *elements = [self.parser parse:@"ab &#65 "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"A"];
}

- (void)testIncompleteEntityAfterWhitespace8
{
	NSArray *elements = [self.parser parse:@"ab &# "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"&#"];
}

//-------- Complete but unknown named entity in text -------

- (void)testCompleteButUnknownEntityInText1
{
	NSArray *elements = [self.parser parse:@"ab&zzz;de "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab&zzz;de"];
}

- (void)testCompleteButUnknownEntityInText2
{
	NSArray *elements = [self.parser parse:@"ab&;de "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab&;de"];
}

//--------

- (void)testBrokenHtmlTag_escapeGam_1
{
	NSArray *elements = [self.parser parse:@"<b>Writers:<\\b <TAB MULTIPLE=4>Karen M"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(5, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[1] withValue:@"Writers:"];
	tag = elements[2];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertTrue(tag.closing);
	[self assertRegularTextIn:elements[3] withValue:@"Karen"];
	[self assertWhitespaceIn:elements[4] withText:@" "];
}

- (void)testBrokenHtmlTag_escapeGam_2
{
	NSArray *elements = [self.parser parse:@"<b>Writers:<\\b<TAB MULTIPLE=4>Karen M"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(4, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[1] withValue:@"Writers:"];
	[self assertRegularTextIn:elements[2] withValue:@"Karen"];
	[self assertWhitespaceIn:elements[3] withText:@" "];
}

- (void)testBrokenHtmlTag_escapeGam_3
{
	NSArray *elements = [self.parser parse:@"<b>Writers:<\\b T<AB MULTIPLE=4>Karen M"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(5, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[1] withValue:@"Writers:"];
	tag = elements[2];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertTrue(tag.closing);
	[self assertRegularTextIn:elements[3] withValue:@"Karen"];
	[self assertWhitespaceIn:elements[4] withText:@" "];
}

- (void)testBrokenHtmlTag_escapeGam_4
{
	NSArray *elements = [self.parser parse:@"<b>Writers:<\\b MULTIPLE='4>'Karen M"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(5, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[1] withValue:@"Writers:"];
	tag = elements[2];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertTrue(tag.closing);
	[self assertRegularTextIn:elements[3] withValue:@"'Karen"];
	[self assertWhitespaceIn:elements[4] withText:@" "];
}

- (void)testBrokenHtmlTag_escapeGam_5
{
	NSArray *elements = [self.parser parse:@"<b>Writers:</b MULTIPLE=\"4>\"Karen M"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(5, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[1] withValue:@"Writers:"];
	tag = elements[2];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertTrue(tag.closing);
	[self assertRegularTextIn:elements[3] withValue:@"\"Karen"];
	[self assertWhitespaceIn:elements[4] withText:@" "];
}

- (void)testBrokenHtmlTag_escapeGam_6
{
	NSArray *elements = [self.parser parse:@"<b>Writers:</b MULTIPLE=4=>Karen M"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(5, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[1] withValue:@"Writers:"];
	tag = elements[2];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertTrue(tag.closing);
	[self assertRegularTextIn:elements[3] withValue:@"Karen"];
	[self assertWhitespaceIn:elements[4] withText:@" "];
}

- (void)testBrokenHtmlTag_escapeGam_7
{
	NSArray *elements = [self.parser parse:@"<b>Writers:</b=>Karen M"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(5, elements.count);
	XTHtmlTag *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[1] withValue:@"Writers:"];
	tag = elements[2];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertTrue(tag.closing);
	[self assertRegularTextIn:elements[3] withValue:@"Karen"];
	[self assertWhitespaceIn:elements[4] withText:@" "];
}

//-------- Test broken HTML tag handling ----------

- (void)testBrokenHtmlTag_afterTagStart_print
{
	[self turnOnBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"io< more asas<b>bold?"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(2, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"io"];
	[self assertRegularTextIn:elements[1] withValue:@"< more asas<b>"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"bold?"];
}

- (void)testBrokenHtmlTag_afterTagStart_suppress
{
	[self turnOffBrokenHtmlOutput];
	
	NSArray *elements = [self.parser parse:@"io< more asas<b>bold?"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"io"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"bold?"];
}

- (void)testIllegalCharInStateAfterStart_print
{
	[self turnOnBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"<<x"];
	ASSERT_PARSER_STATE(XT_HTML_IN_MISFORMED_TAG);
	XCTAssertEqual(0, elements.count);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_MISFORMED_TAG);
	XCTAssertEqual(0, elements.count);
	elements = [self.parser parse:@"moo>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"<<xmoo>"];
}

- (void)testIllegalCharInStateAfterStart_suppress
{
	[self turnOffBrokenHtmlOutput];
	
	NSArray *elements = [self.parser parse:@"<<x"];
	ASSERT_PARSER_STATE(XT_HTML_IN_MISFORMED_TAG);
	XCTAssertEqual(0, elements.count);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_MISFORMED_TAG);
	XCTAssertEqual(0, elements.count);
	elements = [self.parser parse:@"moo>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(0, elements.count);
}

- (void)testBrokenHtmlTag_inTagName_print
{
	[self turnOnBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"mm<h( s=2>rest"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(2, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"mm"];
	[self assertRegularTextIn:elements[1] withValue:@"<h( s=2>"];
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"rest"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
}

- (void)testBrokenHtmlTag_inTagName_suppress
{
	[self turnOffBrokenHtmlOutput];
	
	NSArray *elements = [self.parser parse:@"mm<h( s=2>rest"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"mm"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"rest"];
	
}

- (void)testBrokenHtmlTag_afterTagName_print
{
	[self turnOnBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"mm<h . huh>rest"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(2, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"mm"];
	[self assertRegularTextIn:elements[1] withValue:@"<h . huh>"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"rest"];
}

- (void)testBrokenHtmlTag_afterTagName_suppress
{
	[self turnOffBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"mm<h . huh>rest"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"mm"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"rest"];
}

- (void)testBrokenHtmlTag_atClosingSlash_print
{
	[self turnOnBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"m<br/.>K"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(2, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"m"];
	[self assertRegularTextIn:elements[1] withValue:@"<br/.>"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"K"];
}

- (void)testBrokenHtmlTag_atClosingSlash_suppress
{
	[self turnOffBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"m<br/.>K"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"m"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"K"];
}

- (void)testBrokenHtmlTag_inAttributeName_print
{
	[self turnOnBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"m<p w. mu>pp"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(2, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"m"];
	XTHtmlTag *tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagP class]];
	XCTAssertEqual(2, tag.attributes.count);
	XCTAssertNil([tag attributeAsString:@"1."]);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"mu"]);
	XCTAssertFalse(tag.closing);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"pp"];
}

- (void)testBrokenHtmlTag_inAttributeName_suppress
{
	[self turnOffBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"m<p w. mu>pp"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(2, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"m"];
	XTHtmlTag *tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagP class]];
	XCTAssertEqual(2, tag.attributes.count);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"w."]);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"mu"]);
	XCTAssertFalse(tag.closing);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"pp"];
}

- (void)testBrokenHtmlTag_startingAttributeName_print
{
	[self turnOnBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"m<p w== mu>pp"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(2, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"m"];
	XTHtmlTag *tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagP class]];
	XCTAssertEqual(2, tag.attributes.count);
	XCTAssertEqualObjects(@"=", [tag attributeAsString:@"w"]);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"mu"]);
	XCTAssertFalse(tag.closing);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"pp"];
}

- (void)testBrokenHtmlTag_startingAttributeName_suppress
{
	[self turnOffBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"m<p w== mu>pp"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(2, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"m"];
	XTHtmlTag *tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagP class]];
	XCTAssertEqual(2, tag.attributes.count);
	XCTAssertEqualObjects(@"=", [tag attributeAsString:@"w"]);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"mu"]);
	XCTAssertFalse(tag.closing);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"pp"];
}

- (void)testBrokenHtmlTag_inUnquotedAttributeValue_print
{
	[self turnOnBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"m<p w=x< mu>pp"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(2, elements.count);
	XTHtmlTag *tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagP class]];
	XCTAssertEqual(2, tag.attributes.count);
	XCTAssertEqualObjects(@"x<", [tag attributeAsString:@"w"]);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"mu"]);
	XCTAssertFalse(tag.closing);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"pp"];
}

- (void)testBrokenHtmlTag_inUnquotedAttributeValue_suppress
{
	[self turnOffBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"m>c<p w=x< mu>s "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(3, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"m>c"];
	XTHtmlTag *tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagP class]];
	XCTAssertEqual(2, tag.attributes.count);
	XCTAssertEqualObjects(@"x<", [tag attributeAsString:@"w"]);
	XCTAssertEqualObjects(@"", [tag attributeAsString:@"mu"]);
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[2] withValue:@"s"];
}

//-------- Test pseudo-tags --------------

- (void)testPseudoTagOpen
{
	NSArray *elements = [self.parser parse:@"<.pseudotest>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagPseudoTest class] closing:NO];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(0, elements.count);
}

- (void)testPseudoTagClose
{
	NSArray *elements = [self.parser parse:@"<./pseudotest>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagPseudoTest class] closing:YES];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(0, elements.count);
}

- (void)testPseudoTagClose2
{
	NSArray *elements = [self.parser parse:@"<.\\pseudotest>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagPseudoTest class] closing:YES];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(0, elements.count);
}

- (void)testBrokenPseudoTag_print
{
	[self turnOnBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"ab<. pseudotest>cd"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(2, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	[self assertRegularTextIn:elements[1] withValue:@"<. pseudotest>"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"cd"];
}

- (void)testBrokenPseudoTag_suppress
{
	[self turnOffBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"ab<. pseudotest>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(0, elements.count);
}

- (void)testPseudoTagsIgnored_print
{
	[self turnOnBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"1<.P0>2<.commandsep>3<.convend>4<.roomname>5<.roomdesc>6<.announceObj>7<.convstay>8<.topics>9" \
						                    "<.parser>10<.inputline>11<.commandbegin>12<.a>13<.statusroom>14<.statusscore>15<.commandint>16<.convnode>17" \
											"<.p>18<.notification>19<.roompara>20<.assume>21"
						 ];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(40, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"1"];
	[self assertRegularTextIn:elements[1] withValue:@"<.P0>"];
	[self assertRegularTextIn:elements[2] withValue:@"2"];
	[self assertRegularTextIn:elements[3] withValue:@"<.commandsep>"];
	[self assertRegularTextIn:elements[4] withValue:@"3"];
	[self assertRegularTextIn:elements[5] withValue:@"<.convend>"];
	[self assertRegularTextIn:elements[6] withValue:@"4"];
	[self assertRegularTextIn:elements[7] withValue:@"<.roomname>"];
	[self assertRegularTextIn:elements[8] withValue:@"5"];
	[self assertRegularTextIn:elements[9] withValue:@"<.roomdesc>"];
	[self assertRegularTextIn:elements[10] withValue:@"6"];
	[self assertRegularTextIn:elements[11] withValue:@"<.announceObj>"];
	[self assertRegularTextIn:elements[12] withValue:@"7"];
	[self assertRegularTextIn:elements[13] withValue:@"<.convstay>"];
	[self assertRegularTextIn:elements[14] withValue:@"8"];
	[self assertRegularTextIn:elements[15] withValue:@"<.topics>"];
	[self assertRegularTextIn:elements[16] withValue:@"9"];
	[self assertRegularTextIn:elements[17] withValue:@"<.parser>"];
	[self assertRegularTextIn:elements[18] withValue:@"10"];
	[self assertRegularTextIn:elements[19] withValue:@"<.inputline>"];
	[self assertRegularTextIn:elements[20] withValue:@"11"];
	[self assertRegularTextIn:elements[21] withValue:@"<.commandbegin>"];
	[self assertRegularTextIn:elements[22] withValue:@"12"];
	[self assertRegularTextIn:elements[23] withValue:@"<.a>"];
	[self assertRegularTextIn:elements[24] withValue:@"13"];
	[self assertRegularTextIn:elements[25] withValue:@"<.statusroom>"];
	[self assertRegularTextIn:elements[26] withValue:@"14"];
	[self assertRegularTextIn:elements[27] withValue:@"<.statusscore>"];
	[self assertRegularTextIn:elements[28] withValue:@"15"];
	[self assertRegularTextIn:elements[29] withValue:@"<.commandint>"];
	[self assertRegularTextIn:elements[30] withValue:@"16"];
	[self assertRegularTextIn:elements[31] withValue:@"<.convnode>"];
	[self assertRegularTextIn:elements[32] withValue:@"17"];
	[self assertRegularTextIn:elements[33] withValue:@"<.p>"];
	[self assertRegularTextIn:elements[34] withValue:@"18"];
	[self assertRegularTextIn:elements[35] withValue:@"<.notification>"];
	[self assertRegularTextIn:elements[36] withValue:@"19"];
	[self assertRegularTextIn:elements[37] withValue:@"<.roompara>"];
	[self assertRegularTextIn:elements[38] withValue:@"20"];
	[self assertRegularTextIn:elements[39] withValue:@"<.assume>"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"21"];
}

- (void)testPseudoTagsIgnored_suppress
{
	[self turnOffBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"1<./P0>2<./commandsep>3<./convend>4<./roomname>5<./roomdesc>6<./announceObj>7<./convstay>8<./topics>9" \
						 "<./parser>10<./inputline>11<./commandbegin>12<./a>13<./statusroom>14<./statusscore>15<./commandint>16<./convnode>17" \
						 "<./p>18<./notification>19<./roompara>20<./assume>21"
						 ];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(20, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"1"];
	[self assertRegularTextIn:elements[1] withValue:@"2"];
	[self assertRegularTextIn:elements[2] withValue:@"3"];
	[self assertRegularTextIn:elements[3] withValue:@"4"];
	[self assertRegularTextIn:elements[4] withValue:@"5"];
	[self assertRegularTextIn:elements[5] withValue:@"6"];
	[self assertRegularTextIn:elements[6] withValue:@"7"];
	[self assertRegularTextIn:elements[7] withValue:@"8"];
	[self assertRegularTextIn:elements[8] withValue:@"9"];
	[self assertRegularTextIn:elements[9] withValue:@"10"];
	[self assertRegularTextIn:elements[10] withValue:@"11"];
	[self assertRegularTextIn:elements[11] withValue:@"12"];
	[self assertRegularTextIn:elements[12] withValue:@"13"];
	[self assertRegularTextIn:elements[13] withValue:@"14"];
	[self assertRegularTextIn:elements[14] withValue:@"15"];
	[self assertRegularTextIn:elements[15] withValue:@"16"];
	[self assertRegularTextIn:elements[16] withValue:@"17"];
	[self assertRegularTextIn:elements[17] withValue:@"18"];
	[self assertRegularTextIn:elements[18] withValue:@"19"];
	[self assertRegularTextIn:elements[19] withValue:@"20"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"21"];
}

//-------- Test fixes for specific bugs etc. ----------

- (void)testUnexpectedCharAfterTagStartDarkAngel
{
	NSArray *elements = [self.parser parse:@"<a href=\"http\">How<\\a>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class]];
	[self assertRegularTextIn:elements[1] withValue:@"How"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class]];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(0, elements.count);
}

- (void)testGoldenSkullParchmentIndentBug
{
	NSArray *elements = [self.parser parse:@"cave<BR> Se gyrent"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(5, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"cave"];
	[self assertHtmlTagIn:elements[1] withClass:[XTHtmlTagBr class]];
	[self assertWhitespaceIn:elements[2] withText:@" "];
	[self assertRegularTextIn:elements[3] withValue:@"Se"];
	[self assertWhitespaceIn:elements[4] withText:@" "];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"gyrent"];
}

- (void)testTads2GameIntro
{
	NSArray *elements = [self.parser parse:@"reg1"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(0, elements.count);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"reg1"];

	elements = [self.parser parse:@"<?T2>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagQuestionMarkT2 class]];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(0, elements.count);

	elements = [self.parser parse:@"REG2"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(0, elements.count);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"REG2"];
}

- (void)testAllHopeAbandonMissingNewlineBug
{
	NSArray *elements = [self.parser parse:@"[Press a key to continue...]<br>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(10, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"[Press"];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertRegularTextIn:elements[2] withValue:@"a"];
	[self assertWhitespaceIn:elements[3] withText:@" "];
	[self assertRegularTextIn:elements[4] withValue:@"key"];
	[self assertWhitespaceIn:elements[5] withText:@" "];
	[self assertRegularTextIn:elements[6] withValue:@"to"];
	[self assertWhitespaceIn:elements[7] withText:@" "];
	[self assertRegularTextIn:elements[8] withValue:@"continue...]"];
	XTHtmlTag *tag = elements[9];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];

	elements = [self.parser parse:@"<BR HEIGHT=0>\n"];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];

	elements = [self.parser parse:@"<BR>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(2, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@"\n"];
	tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];

	elements = [self.parser parse:@"<BR HEIGHT=0>\n"];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];

	elements = [self.parser parse:@"<b>The Breakfast Queue</b><br>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(9, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@"\n"];
	tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertFalse(tag.closing);
	[self assertRegularTextIn:elements[2] withValue:@"The"];
	[self assertWhitespaceIn:elements[3] withText:@" "];
	[self assertRegularTextIn:elements[4] withValue:@"Breakfast"];
	[self assertWhitespaceIn:elements[5] withText:@" "];
	[self assertRegularTextIn:elements[6] withValue:@"Queue"];
	tag = elements[7];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
	XCTAssertTrue(tag.closing);
	tag = elements[8];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
}

- (void)testTillDeathSpaceAfterTabBug
{
	NSArray *elements =
		[self.parser parse:@"<TAB MULTIPLE=4>ABOUT<TAB MULTIPLE=4><TAB MULTIPLE=4> - Show some background"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(11, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagTab class]];
	[self assertRegularTextIn:elements[1] withValue:@"ABOUT"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagTab class]];
	[self assertHtmlTagIn:elements[3] withClass:[XTHtmlTagTab class]];
	[self assertWhitespaceIn:elements[4] withText:@" "];
	[self assertRegularTextIn:elements[5] withValue:@"-"];
	[self assertWhitespaceIn:elements[6] withText:@" "];
	[self assertRegularTextIn:elements[7] withValue:@"Show"];
	[self assertWhitespaceIn:elements[8] withText:@" "];
	[self assertRegularTextIn:elements[9] withValue:@"some"];
	[self assertWhitespaceIn:elements[10] withText:@" "];
	
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"background"];
}

- (void)testBeetmongerInitLocExtraNewlineBug
{
	XTHtmlTag *tag;
	NSArray *elements;
	
	elements = [self.parser parse:@"<TAB MULTIPLE=4>Text"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagTab class]];

	elements = [self.parser parse:@" "];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"Text"];

	elements = [self.parser parse:@"MoreText"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@" "];

	elements = [self.parser parse:@"\n"];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"MoreText"];

	elements = [self.parser parse:@"<BR HEIGHT=0>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(2, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@"\n"];
	tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	
	elements = [self.parser parse:@"<TAB MULTIPLE=4>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagTab class]];

	elements = [self.parser parse:@"\n"];
	ASSERT_PARSER_STATE(XT_HTML_IN_WHITESPACE);
	XCTAssertEqual(0, elements.count);
	
	elements = [self.parser parse:@"<BR HEIGHT=0>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(2, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@"\n"];
	tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	
	elements = [self.parser parse:@"<BR HEIGHT=0>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	
	elements = [self.parser parse:@"<TAB MULTIPLE=4>EvenMoreText"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagTab class]];

	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"EvenMoreText"];
}

- (void)testDoubleQuotedFontFaceBug
{
	NSArray *elements = [self.parser parse:@"<FONT FACE=\"Courier\">"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTagTitle *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"Courier", [tag attributeAsString:@"FACE"]);
	XCTAssertEqualObjects(@"Courier", [tag attributeAsString:@"face"]);
	XCTAssertEqualObjects(@"Courier", [tag attributeAsString:@"FacE"]);

	elements = [self.parser parse:@"<Font Face='Courier'>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"Courier", [tag attributeAsString:@"FACE"]);
	XCTAssertEqualObjects(@"Courier", [tag attributeAsString:@"face"]);
	XCTAssertEqualObjects(@"Courier", [tag attributeAsString:@"Face"]);
	
	elements = [self.parser parse:@"<Font Face=Courier>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagFont class]];
	XCTAssertEqual(1, tag.attributes.count);
	XCTAssertEqualObjects(@"Courier", [tag attributeAsString:@"FACE"]);
	XCTAssertEqualObjects(@"Courier", [tag attributeAsString:@"face"]);
	XCTAssertEqualObjects(@"Courier", [tag attributeAsString:@"Face"]);
}

- (void)testMagicEnspSpaceBug
{
	NSArray *elements = [self.parser parse:@"mud.&#8194; Rain"];
	XCTAssertEqual(3, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	[self assertRegularTextIn:elements[0] withValue:@"mud."];
	[self assertSpecialSpaceIn:elements[1] withChar:8194];
	[self assertWhitespaceIn:elements[2] withText:@" "];
	
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	[self assertRegularTextIn:elements[0] withValue:@"Rain"];
}

- (void)testGameTitle
{
	NSArray *elements = [self.parser parse:@"<title>The Game</title>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(5, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagTitle class] closing:NO];
	[self assertRegularTextIn:elements[1] withValue:@"The"];
	[self assertWhitespaceIn:elements[2] withText:@" "];
	[self assertRegularTextIn:elements[3] withValue:@"Game"];
	[self assertHtmlTagIn:elements[4] withClass:[XTHtmlTagTitle class] closing:YES];

	elements = [self.parser parse:@"<br>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagBr class] closing:NO];
	XCTAssertEqual(0, ((XTHtmlTag*)elements[0]).attributes.count);
}

- (void)testTwoStandaloneTagsInSameString
{
	NSArray *elements = [self.parser parse:@"<br height=2><br>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(2, elements.count);
	XTHtmlTagBr *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(2, [tag attributeAsUInt:@"height"]);
	XCTAssertFalse(tag.closing);
	tag = elements[1];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertEqual(0, tag.attributes.count);
	XCTAssertFalse(tag.closing);
}

- (void)testTwoStandaloneTagsInDifferentStrings
{
	NSArray *elements = [self.parser parse:@"<br height=2>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTagBr *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertFalse(tag.closing);
	XCTAssertEqual(2, [tag attributeAsUInt:@"height"]);

	elements = [self.parser parse:@"<br>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagBr class]];
	XCTAssertFalse(tag.closing);
	XCTAssertEqual(0, tag.attributes.count);
}

- (void)testFlushUnusedTagText_1a
{
	NSArray *elements = [self.parser parse:@"<"];
	ASSERT_PARSER_STATE(XT_HTML_AFTER_TAG_START);
	XCTAssertEqual(0, elements.count);
	elements = [self.parser flush];
	XCTAssertEqual(0, elements.count);

	elements = [self.parser parse:@"b>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	XTHtmlTagB *tag = elements[0];
	[self assertHtmlTagIn:tag withClass:[XTHtmlTagB class]];
}

- (void)testFlushUnusedTagText_1b
{
	NSArray *elements = [self.parser parse:@"<br"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TAG_NAME);
	XCTAssertEqual(0, elements.count);

	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TAG_NAME);
	XCTAssertEqual(0, elements.count);
}

- (void)testFlushUnusedTagText_1c
{
	NSArray *elements = [self.parser parse:@"<b/"];
	ASSERT_PARSER_STATE(XT_HTML_AT_CLOSING_SLASH);
	XCTAssertEqual(0, elements.count);

	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_AT_CLOSING_SLASH);
	XCTAssertEqual(0, elements.count);
}

- (void)testFlushUnusedTagText_2
{
	NSArray *elements = [self.parser parse:@" <br"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TAG_NAME);
	XCTAssertEqual(1, elements.count);
	[self assertWhitespaceIn:elements[0] withText:@" "];

	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TAG_NAME);
	XCTAssertEqual(0, elements.count);
}

- (void)testFlushUnusedTagText_3
{
	NSArray *elements = [self.parser parse:@"xy<br"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TAG_NAME);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"xy"];

	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TAG_NAME);
	XCTAssertEqual(0, elements.count);
}

- (void)testUnknownTag_suppress
{
	[self turnOffBrokenHtmlOutput];

	NSArray *elements = [self.parser parse:@"<bongo>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(0, elements.count);
	elements = [self.parser flush];
	XCTAssertEqual(0, elements.count);
	
	elements = [self.parser parse:@"<bongo foo bar>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(0, elements.count);
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(0, elements.count);

	elements = [self.parser parse:@"a<bongo>cd"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"cd"];

	elements = [self.parser parse:@"ab<bongo ff m>cd<br>ef<pooba"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TAG_NAME);
	XCTAssertEqual(4, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	[self assertRegularTextIn:elements[1] withValue:@"cd"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagBr class]];
	[self assertRegularTextIn:elements[3] withValue:@"ef"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TAG_NAME);
	XCTAssertEqual(0, elements.count);
}

- (void)testUnknownTag_print
{
	[self turnOnBrokenHtmlOutput];
	
	NSArray *elements = [self.parser parse:@"<bongo>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"<bongo>"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(0, elements.count);
	
	elements = [self.parser parse:@"<bongo foo bar>"];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"<bongo foo bar>"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_INITIAL);
	XCTAssertEqual(0, elements.count);
	
	elements = [self.parser parse:@"a<bongo>cd"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(2, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a"];
	[self assertRegularTextIn:elements[1] withValue:@"<bongo>"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TEXT);
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"cd"];
	
	elements = [self.parser parse:@"ab<bongo ff m>cd<br>ef<pooba"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TAG_NAME);
	XCTAssertEqual(5, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"ab"];
	[self assertRegularTextIn:elements[1] withValue:@"<bongo ff m>"];
	[self assertRegularTextIn:elements[2] withValue:@"cd"];
	[self assertHtmlTagIn:elements[3] withClass:[XTHtmlTagBr class]];
	[self assertRegularTextIn:elements[4] withValue:@"ef"];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TAG_NAME);
	XCTAssertEqual(0, elements.count);
}

- (void)test_GoldenSkull_extraNewlineAfterAboutIssue
{
	NSArray *elements = [self.parser parse:@"<CENTER> <IMG SRC=\"title.jpg\"> </CENTER> <P> <BLOCKQUOTE> <FONT"];
	ASSERT_PARSER_STATE(XT_HTML_IN_TAG_NAME);
	XCTAssertEqual(10, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagCenter class] closing:NO];
	[self assertWhitespaceIn:elements[1] withText:@" "];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagImg class] closing:NO];
	[self assertWhitespaceIn:elements[3] withText:@" "];
	[self assertHtmlTagIn:elements[4] withClass:[XTHtmlTagCenter class] closing:YES];
	[self assertWhitespaceIn:elements[5] withText:@" "];
	[self assertHtmlTagIn:elements[6] withClass:[XTHtmlTagP class] closing:NO];
	[self assertWhitespaceIn:elements[7] withText:@" "];
	[self assertHtmlTagIn:elements[8] withClass:[XTHtmlTagBlockQuote class] closing:NO];
	[self assertWhitespaceIn:elements[9] withText:@" "];
	elements = [self.parser flush];
	ASSERT_PARSER_STATE(XT_HTML_IN_TAG_NAME);
	XCTAssertEqual(0, elements.count);
}

- (void)test_aTag_empty_bug
{
	NSArray *elements = [self.parser parse:@"<a HREF=\"http://www.tads.org\">TADS</a>"];
	XCTAssertEqual(3, elements.count);
	[self assertHtmlTagIn:elements[0] withClass:[XTHtmlTagA class] closing:NO];
	XTHtmlTagA *tag = elements[0];
	XCTAssertEqualObjects(@"http://www.tads.org", [tag attributeAsString:@"href"]);
	[self assertRegularTextIn:elements[1] withValue:@"TADS"];
	[self assertHtmlTagIn:elements[2] withClass:[XTHtmlTagA class] closing:YES];
}

- (void)test_bannerTag
{
	NSArray *elements = [self.parser parse:@"a<banner id='moo'>text</banner>bbb"];
	XCTAssertEqual(4, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"a"];
	[self assertHtmlTagIn:elements[1] withClass:[XTHtmlTagBanner class] closing:NO];
	[self assertRegularTextIn:elements[2] withValue:@"text"];
	[self assertHtmlTagIn:elements[3] withClass:[XTHtmlTagBanner class] closing:YES];
	elements = [self.parser flush];
	XCTAssertEqual(1, elements.count);
	[self assertRegularTextIn:elements[0] withValue:@"bbb"];
}
*/

//------------- Supports functions for tests -------------------

//TODO make macros instead, so we can see which tests fail!

- (void)assertRegularTextIn:(id)obj withValue:(NSString *)string
{
	XCTAssertTrue([obj isKindOfClass:[NSString class]]);
	XCTAssertEqualObjects(string, obj);
}

- (void)assertHtmlTagIn:(id)obj withClass:(Class)class
{
	if (! [obj isKindOfClass:class]) {
		int brkpt = 1;
	}
	XCTAssertTrue([obj isKindOfClass:class]);
}

- (void)assertHtmlTagIn:(id)obj withClass:(Class)class closing:(BOOL)closing
{
	XCTAssertTrue([obj isKindOfClass:class] && ((XTHtmlTag *)obj).closing == closing);
}

- (void)assertWhitespaceIn:(id)obj withText:(NSString *)text
{
	XTHtmlTagWhitespace *ws = ([obj isKindOfClass:[XTHtmlTagWhitespace class]] ? (XTHtmlTagWhitespace *)obj : nil);
	
	XCTAssertTrue(ws != nil && [text isEqualToString:ws.text]);
}

- (void)assertQuotedSpaceIn:(id)obj
{
	XTHtmlTagQuotedSpace *qs = ([obj isKindOfClass:[XTHtmlTagQuotedSpace class]] ? (XTHtmlTagQuotedSpace *)obj : nil);
	
	XCTAssertTrue(qs != nil);
}

- (void)assertNonbreakingSpaceIn:(id)obj
{
	XTHtmlTagNonbreakingSpace *nbs = ([obj isKindOfClass:[XTHtmlTagNonbreakingSpace class]] ? (XTHtmlTagNonbreakingSpace *)obj : nil);
	
	XCTAssertTrue(nbs != nil);
}

- (void)assertSpecialSpaceIn:(id)obj withChar:(unichar)ch
{
	XTHtmlTagSpecialSpace *ss = ([obj isKindOfClass:[XTHtmlTagSpecialSpace class]] ? (XTHtmlTagSpecialSpace *)obj : nil);
	
	XCTAssertTrue(ss != nil);
	
	XCTAssertEqual(ch, ss.ch);
}

//-----------

- (void)turnOffBrokenHtmlOutput
{
	XTPrefs *prefs = [XTPrefs prefs];
	prefs.printBrokenHtmlMarkup = [NSNumber numberWithBool:NO];
}

- (void)turnOnBrokenHtmlOutput
{
	XTPrefs *prefs = [XTPrefs prefs];
	prefs.printBrokenHtmlMarkup = [NSNumber numberWithBool:YES];
}

@end
