#/usr/bin/perl -w

# A tranliteration of FrameworkTest.java, which is
#   Copyright (c) 2002 Cunningham & Cunningham, Inc.
#   Released under the terms of the GNU General Public License version 2 or later.
#
# Dave W. Smith <dws@postcognitive.com>

use strict;
use Test;
BEGIN { plan test => 61 }
use lib qw(..);
use Fit::Parse;
use Fit::TypeAdapter;

# Test Parsing
my $p = new Fit::Parse("leader<Table foo=2>body</table>trailer", qw(table));
ok($p->leader(), "leader");		# 1
ok($p->tag(), "<Table foo=2>");		# 2
ok($p->body(), "body");			# 3
ok($p->trailer(), "trailer");		# 4

# Test Recursing
$p = new Fit::Parse("leader<table><TR><Td>body</tD></TR></table>trailer");
ok($p->body(), undef);				#5
ok($p->parts()->body(), undef);			#6
ok($p->parts()->parts()->body(), "body");	#7

# Test Iterating
# Parse p = new Parse("leader<table><tr><td>one</td><td>two</td><td>three</td></tr></table>trailer");
# assertEquals("one", p.parts.parts.body);
# assertEquals("two", p.parts.parts.more.body);
# assertEquals("three", p.parts.parts.more.more.body);

$p = new Fit::Parse("leader<table><tr><td>one</td><td>two</td><td>three</td></tr></table>trailer");
ok($p->parts()->parts()->body(), "one");			# 8
ok($p->parts()->parts()->more()->body(), "two");		# 9
ok($p->parts()->parts()->more()->more()->body(), "three");	# 10

# Test Indexing
# Parse p = new Parse("leader<table><tr><td>one</td><td>two</td><td>three</td></tr><tr><td>four</td></tr></table>trailer");
# assertEquals("one", p.at(0,0,0).body);
# assertEquals("two", p.at(0,0,1).body);
# assertEquals("three", p.at(0,0,2).body);
# assertEquals("three", p.at(0,0,3).body);
# assertEquals("three", p.at(0,0,4).body);
# assertEquals("four", p.at(0,1,0).body);
# assertEquals("four", p.at(0,1,1).body);
# assertEquals("four", p.at(0,2,0).body);
# assertEquals(1, p.size());
# assertEquals(2, p.parts.size());
# assertEquals(3, p.parts.parts.size());
# assertEquals("one", p.leaf().body);
# assertEquals("four", p.parts.last().leaf().body);

my $html = "leader<table><tr><td>one</td><td>two</td><td>three</td></tr><tr><td>four</td></tr></table>trailer";
$p = new Fit::Parse($html);
ok($p->size(), 1);					# 11
ok($p->parts()->size(), 2);				# 12
ok($p->parts()->parts()->size(), 3);			# 13
ok($p->leaf()->body(), "one");				# 14
ok($p->parts()->last()->leaf()->body(), "four");	# 15
ok($p->at(0,0,0)->body(), "one");			# 16
ok($p->at(0,0,1)->body(), "two");			# 17
ok($p->at(0,0,2)->body(), "three");			# 18
ok($p->at(0,0,3)->body(), "three");			# 19
ok($p->at(0,0,4)->body(), "three");			# 20
ok($p->at(0,1,0)->body(), "four");			# 21
ok($p->at(0,1,1)->body(), "four");			# 22
ok($p->at(0,2,0)->body(), "four");			# 23

# Test ParseException 
eval {
  $p = new Fit::Parse("leader<table><tr><th>one</th><th>two</th><th>three</th></tr><tr><td>four</td></tr></table>trailer");
};
ok($@, "Can't find tag: td\n");				# 24

# Test Text
# String tags[] ={"td"};
# Parse p = new Parse("<td>a&lt;b</td>", tags);
# assertEquals("a&lt;b", p.body);
# assertEquals("a<b", p.text());
# p = new Parse("<td>\ta&gt;b&nbsp;&amp;&nbsp;b>c &&&nbsp;</td>", tags);
# assertEquals("a>b & b>c &&", p.text());
# p = new Parse("<TD><P><FONT FACE=\"Arial\" SIZE=2>GroupTestFixture</FONT></TD>", tags);
# assertEquals("GroupTestFixture",p.text());

$p = new Fit::Parse("<td>a&lt;b</td>", qw(td));
ok($p->body(), "a&lt;b");				# 25
ok($p->text(), "a<b");					# 26

$p = new Fit::Parse("<td>\ta&gt;b&nbsp;&amp;&nbsp;b>c &&&nbsp;</td>", qw(td));
ok($p->text(), "a>b & b>c &&");				# 27

$p = new Fit::Parse("<TD><P><FONT FACE=\"Arial\" SIZE=2>GroupTestFixture</FONT></TD>", qw(td));
ok($p->text(), "GroupTestFixture");			# 28


# Test Unescape
# assertEquals("a<b", Parse.unescape("a&lt;b"));
# assertEquals("a>b & b>c &&", Parse.unescape("a&gt;b&nbsp;&amp;&nbsp;b>c &&"));
ok(Fit::Parse::unescape("a&lt;b"), "a<b");		# 29
ok(Fit::Parse::unescape("a&gt;b&nbsp;&amp;&nbsp;b>c &&"), "a>b & b>c &&");	# 30

# Test Unformat
# assertEquals("ab",Parse.unformat("<font size=+1>a</font>b"));
# assertEquals("ab",Parse.unformat("a<font size=+1>b</font>"));
# assertEquals("a<b",Parse.unformat("a<b"));
ok(Fit::Parse::unformat("<font size=+1>a</font>b"), "ab");	# 31
ok(Fit::Parse::unformat("a<font size=+1>b</font>"), "ab");	# 32
ok(Fit::Parse::unformat("a<b"), "a<b");				# 33

# Test print

$p = new Fit::Parse($html);
my $s = $p->print();
ok($p->trailer(), "trailer");					# 34
ok($s, $html);							# 35

# Test addToBody, addToTag

$p = new Fit::Parse("<td>bar</td>", qw(td));
$p->addToBody(' baz');
ok($p->print(), '<td>bar baz</td>');				# 36
$p->addToTag(' id="foo"');
ok($p->print(), '<td id="foo">bar baz</td>');			# 37


# Test TypeAdapter
my $f = new Fit::TestFixture();
ok(defined($f));						# 38

# TypeAdapter a = TypeAdapter.on(f, f.getClass().getField("sampleInt"));
# a.set(a.parse("123456"));
# assertEquals(123456, f.sampleInt);
my $a = Fit::TypeAdapter::onField($f, "sampleInt");
ok(defined($a));						# 39
ok(ref($a), "Fit::GenericAdapter");				# 40 Meta test
ok($a->parse("-23456"), "-23456");				# 41;
# assertEquals("-234567", a.parse("-234567").toString());
$a->set($a->parse("123456"));
ok($f->{'sampleInt'}, "123456");				# 42 Note: ->toString() is a Java-ism

# a = TypeAdapter.on(f, f.getClass().getField("sampleInteger"));
# a.set(a.parse("54321"));
# assertEquals("54321", f.sampleInteger.toString());
$a = Fit::TypeAdapter::onField($f, "sampleInteger");
ok(ref($a), "Fit::GenericAdapter");				# 43 Meta test
$a->set($a->parse("54321"));
ok($f->{'sampleInteger'}, "54321");				# 44

# a = TypeAdapter.on(f, f.getClass().getMethod("pi", new Class[] {}));
# assertEquals(3.14159, ((Double)a.invoke()).doubleValue(), 0.00001);
# assertEquals(new Double(3.14159862), a.invoke());
$a = Fit::TypeAdapter::onMethod($f, "pi");
ok(ref($a), "Fit::GenericAdapter");				# 45
ok($a->invoke(), 3.14159);					# 46

# a = TypeAdapter.on(f, f.getClass().getField("sampleArray"));
# a.set(a.parse("1,2,3"));
# assertEquals(1, f.sampleArray[0]);
# assertEquals(2, f.sampleArray[1]);
# assertEquals(3, f.sampleArray[2]);
# assertEquals("1,2,3", a.toString(f.sampleArray));
# assertTrue(a.equals(new int [] {1,2,3}, f.sampleArray));
$a = Fit::TypeAdapter::onField($f, "sampleArray");
ok(ref($a), "Fit::GenericArrayAdapter");			# 47
$a->set($a->parse("1,2,3"));
ok($f->{'sampleArray'}->[0], 1);				# 48
ok($f->{'sampleArray'}->[1], 2);				# 49
ok($f->{'sampleArray'}->[2], 3);				# 50
ok($a->toString($f->{'sampleArray'}), "1,2,3");			# 51
ok($a->equals($f->{'sampleArray'}, [1,2,3]));			# 52

# The rest of the TypeAdapter tests don't make sense on Perl objects

# Test escape
# String junk = "!@#$%^*()_-+={}|[]\\:\";',./?`";
# assertEquals(junk, Fixture.escape(junk));
# assertEquals("", Fixture.escape(""));
# assertEquals("&lt;", Fixture.escape("<"));
# assertEquals("&lt;&lt;", Fixture.escape("<<"));
# assertEquals("x&lt;", Fixture.escape("x<"));
# assertEquals("&amp;", Fixture.escape("&"));
# assertEquals("&lt;&amp;&lt;", Fixture.escape("<&<"));
# assertEquals("&amp;&lt;&amp;", Fixture.escape("&<&"));
# assertEquals("a &lt; b &amp;&amp; c &lt; d", Fixture.escape("a < b && c < d"));
 
my $junk = "!@#$%^*()_-+={}|[]\\:\";',./?`";
ok(Fit::Fixture::escape(""), "");				# 53
ok(Fit::Fixture::escape($junk), $junk);				# 54
ok(Fit::Fixture::escape("<"), "&lt;");				# 55
ok(Fit::Fixture::escape("<<"), "&lt;&lt;");			# 56
ok(Fit::Fixture::escape("x<"), "x&lt;");			# 57
ok(Fit::Fixture::escape("&"), "&amp;");				# 58
ok(Fit::Fixture::escape("<&<"), "&lt;&amp;&lt;");		# 59
ok(Fit::Fixture::escape("&<&"), "&amp;&lt;&amp;");		# 60
ok(Fit::Fixture::escape("a < b && c < d"), "a &lt; b &amp;&amp; c &lt; d");	# 61




# --- Classes Used above ----

package Fit::TestFixture;
use strict;

use base qw(Fit::Fixture);

sub new {
    my $pkg = shift;
    my $self = $pkg->SUPER::new(@_);
    $self->{'sampleArray'} = [];
    return $self;
}

sub pi { return 3.14159 }
1;
