| 1 |
wakaba |
1.1 |
#!/usr/bin/perl |
| 2 |
|
|
use strict; |
| 3 |
|
|
|
| 4 |
|
|
use lib qw[/home/wakaba/work/manakai2/lib]; ## TODO: ... |
| 5 |
|
|
|
| 6 |
|
|
use Test; |
| 7 |
|
|
|
| 8 |
|
|
BEGIN { plan tests => 548 } |
| 9 |
|
|
|
| 10 |
|
|
require Whatpm::CSS::Parser; |
| 11 |
|
|
require Message::DOM::Window; |
| 12 |
|
|
|
| 13 |
|
|
require Message::DOM::DOMImplementation; |
| 14 |
|
|
my $dom = Message::DOM::DOMImplementation->new; |
| 15 |
|
|
|
| 16 |
|
|
my $DefaultComputed; |
| 17 |
|
|
my $DefaultComputedText; |
| 18 |
|
|
|
| 19 |
|
|
for my $file_name (map {"t/$_"} qw( |
| 20 |
|
|
css-1.dat |
| 21 |
|
|
)) { |
| 22 |
|
|
print "# $file_name\n"; |
| 23 |
|
|
open my $file, '<', $file_name or die "$0: $file_name: $!"; |
| 24 |
|
|
|
| 25 |
|
|
my $all_test = {document => {}, test => []}; |
| 26 |
|
|
my $test; |
| 27 |
|
|
my $mode = 'data'; |
| 28 |
|
|
my $doc_id; |
| 29 |
|
|
my $selectors; |
| 30 |
|
|
while (<$file>) { |
| 31 |
|
|
s/\x0D\x0A/\x0A/; |
| 32 |
|
|
if (/^#data$/) { |
| 33 |
|
|
undef $test; |
| 34 |
|
|
$test->{data} = ''; |
| 35 |
|
|
push @{$all_test->{test}}, $test; |
| 36 |
|
|
$mode = 'data'; |
| 37 |
|
|
} elsif (/#(csstext|cssom)$/) { |
| 38 |
|
|
$test->{$1} = ''; |
| 39 |
|
|
$mode = $1; |
| 40 |
|
|
} elsif (/#(computed(?>text)?) (\S+) (.+)$/) { |
| 41 |
|
|
$test->{$1}->{$doc_id = $2}->{$selectors = $3} = ''; |
| 42 |
|
|
$mode = $1; |
| 43 |
|
|
} elsif (/^#html (\S+)$/) { |
| 44 |
|
|
undef $test; |
| 45 |
|
|
$test->{format} = 'html'; |
| 46 |
|
|
$test->{data} = ''; |
| 47 |
|
|
$all_test->{document}->{$1} = $test; |
| 48 |
|
|
$mode = 'data'; |
| 49 |
wakaba |
1.2 |
} elsif (/^#errors$/) { |
| 50 |
|
|
$test->{errors} = []; |
| 51 |
|
|
$mode = 'errors'; |
| 52 |
|
|
$test->{data} =~ s/\x0D?\x0A\z//; |
| 53 |
wakaba |
1.1 |
} elsif (defined $test->{data} and /^$/) { |
| 54 |
|
|
undef $test; |
| 55 |
|
|
} else { |
| 56 |
|
|
if ({data => 1, cssom => 1, csstext => 1}->{$mode}) { |
| 57 |
|
|
$test->{$mode} .= $_; |
| 58 |
|
|
} elsif ($mode eq 'computed' or $mode eq 'computedtext') { |
| 59 |
|
|
$test->{$mode}->{$doc_id}->{$selectors} .= $_; |
| 60 |
wakaba |
1.2 |
} elsif ($mode eq 'errors') { |
| 61 |
|
|
tr/\x0D\x0A//d; |
| 62 |
|
|
push @{$test->{errors}}, $_; |
| 63 |
wakaba |
1.1 |
} else { |
| 64 |
|
|
die "Line $.: $_"; |
| 65 |
|
|
} |
| 66 |
|
|
} |
| 67 |
|
|
} |
| 68 |
|
|
|
| 69 |
|
|
for my $data (values %{$all_test->{document}}) { |
| 70 |
|
|
if ($data->{format} eq 'html') { |
| 71 |
|
|
my $doc = $dom->create_document; |
| 72 |
|
|
$doc->manakai_is_html (1); |
| 73 |
|
|
$doc->inner_html ($data->{data}); |
| 74 |
|
|
$data->{document} = $doc; |
| 75 |
|
|
} else { |
| 76 |
|
|
die "Test data format $data->{format} is not supported"; |
| 77 |
|
|
} |
| 78 |
|
|
} |
| 79 |
|
|
|
| 80 |
|
|
for my $test (@{$all_test->{test}}) { |
| 81 |
|
|
my ($p, $css_options) = get_parser (); |
| 82 |
|
|
|
| 83 |
wakaba |
1.2 |
my @actual_error; |
| 84 |
wakaba |
1.1 |
$p->{onerror} = sub { |
| 85 |
|
|
my (%opt) = @_; |
| 86 |
wakaba |
1.2 |
my $uri = ${$opt{uri}}; |
| 87 |
|
|
$uri =~ s[^thismessage:/][]; |
| 88 |
|
|
push @actual_error, join ';', |
| 89 |
|
|
$uri, $opt{token}->{line}, $opt{token}->{column}, |
| 90 |
|
|
$opt{level}, |
| 91 |
|
|
$opt{type} . (defined $opt{value} ? ','.$opt{value} : ''); |
| 92 |
wakaba |
1.1 |
}; |
| 93 |
|
|
|
| 94 |
|
|
my $ss = $p->parse_char_string ($test->{data}); |
| 95 |
wakaba |
1.2 |
|
| 96 |
|
|
ok ((join "\n", @actual_error), (join "\n", @{$test->{errors} or []}), |
| 97 |
|
|
"#result ($test->{data})"); |
| 98 |
wakaba |
1.1 |
|
| 99 |
|
|
if (defined $test->{cssom}) { |
| 100 |
|
|
my $actual = serialize_cssom ($ss); |
| 101 |
|
|
ok $actual, $test->{cssom}, "#cssom ($test->{data})"; |
| 102 |
|
|
} |
| 103 |
|
|
|
| 104 |
|
|
if (defined $test->{csstext}) { |
| 105 |
|
|
my $actual = $ss->css_text; |
| 106 |
|
|
ok $actual, $test->{csstext}, "#csstext ($test->{data})"; |
| 107 |
|
|
} |
| 108 |
|
|
|
| 109 |
|
|
for my $doc_id (keys %{$test->{computed} or {}}) { |
| 110 |
|
|
for my $selectors (keys %{$test->{computed}->{$doc_id}}) { |
| 111 |
|
|
my ($window, $style) = get_computed_style |
| 112 |
|
|
($all_test, $doc_id, $selectors, $dom, $css_options, $ss); |
| 113 |
|
|
## NOTE: $window is the root object, so that we must keep it |
| 114 |
|
|
## referenced in this block. |
| 115 |
|
|
|
| 116 |
|
|
my $actual = serialize_style ($style, ''); |
| 117 |
|
|
my $expected = $DefaultComputed; |
| 118 |
|
|
my $diff = $test->{computed}->{$doc_id}->{$selectors}; |
| 119 |
|
|
($actual, $expected) = apply_diff ($actual, $expected, $diff); |
| 120 |
|
|
ok $actual, $expected, |
| 121 |
|
|
"#computed $doc_id $selectors ($test->{data})"; |
| 122 |
|
|
} |
| 123 |
|
|
} |
| 124 |
|
|
|
| 125 |
|
|
for my $doc_id (keys %{$test->{computedtext} or {}}) { |
| 126 |
|
|
for my $selectors (keys %{$test->{computedtext}->{$doc_id}}) { |
| 127 |
|
|
my ($window, $style) = get_computed_style |
| 128 |
|
|
($all_test, $doc_id, $selectors, $dom, $css_options, $ss); |
| 129 |
|
|
## NOTE: $window is the root object, so that we must keep it |
| 130 |
|
|
## referenced in this block. |
| 131 |
|
|
|
| 132 |
|
|
my $actual = $style->css_text; |
| 133 |
|
|
my $expected = $DefaultComputedText; |
| 134 |
|
|
my $diff = $test->{computedtext}->{$doc_id}->{$selectors}; |
| 135 |
|
|
($actual, $expected) = apply_diff ($actual, $expected, $diff); |
| 136 |
|
|
"#computedtext $doc_id $selectors ($test->{data})"; |
| 137 |
|
|
ok $actual, $expected, |
| 138 |
|
|
"#computedtext $doc_id $selectors ($test->{data})"; |
| 139 |
|
|
} |
| 140 |
|
|
} |
| 141 |
|
|
} |
| 142 |
|
|
} |
| 143 |
|
|
|
| 144 |
|
|
my @longhand; |
| 145 |
|
|
my @shorthand; |
| 146 |
|
|
BEGIN { |
| 147 |
|
|
@longhand = qw/ |
| 148 |
|
|
background-attachment background-color background-image |
| 149 |
|
|
background-position-x background-position-y |
| 150 |
|
|
background-repeat border-bottom-color |
| 151 |
|
|
border-bottom-style border-bottom-width border-collapse |
| 152 |
|
|
border-left-color |
| 153 |
|
|
border-left-style border-left-width border-right-color |
| 154 |
|
|
border-right-style border-right-width |
| 155 |
|
|
-manakai-border-spacing-x -manakai-border-spacing-y |
| 156 |
|
|
border-top-color border-top-style border-top-width bottom |
| 157 |
|
|
caption-side clear color cursor direction display empty-cells float |
| 158 |
|
|
font-family font-size font-style font-variant font-weight height left |
| 159 |
|
|
letter-spacing line-height |
| 160 |
|
|
list-style-image list-style-position list-style-type |
| 161 |
|
|
margin-bottom margin-left margin-right margin-top |
| 162 |
|
|
max-height max-width min-height min-width opacity -moz-opacity |
| 163 |
|
|
orphans outline-color outline-style outline-width overflow |
| 164 |
|
|
padding-bottom padding-left padding-right padding-top |
| 165 |
|
|
page-break-after page-break-before page-break-inside |
| 166 |
|
|
position right table-layout |
| 167 |
|
|
text-align text-decoration text-indent text-transform |
| 168 |
|
|
top unicode-bidi vertical-align visibility white-space width widows |
| 169 |
|
|
word-spacing z-index |
| 170 |
|
|
/; |
| 171 |
|
|
@shorthand = qw/ |
| 172 |
|
|
background background-position |
| 173 |
|
|
border border-color border-style border-width border-spacing |
| 174 |
|
|
border-top border-right border-bottom border-left |
| 175 |
|
|
font list-style margin outline padding |
| 176 |
|
|
/; |
| 177 |
|
|
$DefaultComputedText = q[ border-spacing: 0px; |
| 178 |
|
|
background: transparent none repeat scroll 0% 0%; |
| 179 |
|
|
border: 0px none -manakai-default; |
| 180 |
|
|
border-collapse: separate; |
| 181 |
|
|
bottom: auto; |
| 182 |
|
|
caption-side: top; |
| 183 |
|
|
clear: none; |
| 184 |
|
|
color: -manakai-default; |
| 185 |
|
|
cursor: auto; |
| 186 |
|
|
direction: ltr; |
| 187 |
|
|
display: inline; |
| 188 |
|
|
empty-cells: show; |
| 189 |
|
|
float: none; |
| 190 |
|
|
font-family: -manakai-default; |
| 191 |
|
|
font-size: 16px; |
| 192 |
|
|
font-style: normal; |
| 193 |
|
|
font-variant: normal; |
| 194 |
|
|
font-weight: 400; |
| 195 |
|
|
height: auto; |
| 196 |
|
|
left: auto; |
| 197 |
|
|
letter-spacing: normal; |
| 198 |
|
|
line-height: normal; |
| 199 |
|
|
list-style-image: none; |
| 200 |
|
|
list-style-position: outside; |
| 201 |
|
|
list-style-type: disc; |
| 202 |
|
|
margin-bottom: 0px; |
| 203 |
|
|
margin-left: 0px; |
| 204 |
|
|
margin-right: 0px; |
| 205 |
|
|
margin-top: 0px; |
| 206 |
|
|
max-height: none; |
| 207 |
|
|
max-width: none; |
| 208 |
|
|
min-height: 0px; |
| 209 |
|
|
min-width: 0px; |
| 210 |
|
|
opacity: 1; |
| 211 |
|
|
orphans: 2; |
| 212 |
|
|
outline: 0px none invert; |
| 213 |
|
|
overflow: visible; |
| 214 |
|
|
padding-bottom: 0px; |
| 215 |
|
|
padding-left: 0px; |
| 216 |
|
|
padding-right: 0px; |
| 217 |
|
|
padding-top: 0px; |
| 218 |
|
|
page-break-after: auto; |
| 219 |
|
|
page-break-before: auto; |
| 220 |
|
|
page-break-inside: auto; |
| 221 |
|
|
position: static; |
| 222 |
|
|
right: auto; |
| 223 |
|
|
table-layout: auto; |
| 224 |
|
|
text-align: begin; |
| 225 |
|
|
text-decoration: none; |
| 226 |
|
|
text-indent: 0px; |
| 227 |
|
|
text-transform: none; |
| 228 |
|
|
top: auto; |
| 229 |
|
|
unicode-bidi: normal; |
| 230 |
|
|
vertical-align: baseline; |
| 231 |
|
|
visibility: visible; |
| 232 |
|
|
white-space: normal; |
| 233 |
|
|
widows: 2; |
| 234 |
|
|
width: auto; |
| 235 |
|
|
word-spacing: normal; |
| 236 |
|
|
z-index: auto; |
| 237 |
|
|
]; |
| 238 |
|
|
$DefaultComputed = $DefaultComputedText; |
| 239 |
|
|
$DefaultComputed =~ s/^ /| /gm; |
| 240 |
|
|
$DefaultComputed =~ s/;$//gm; |
| 241 |
|
|
$DefaultComputed .= q[| -manakai-border-spacing-x: 0px |
| 242 |
|
|
| -manakai-border-spacing-y: 0px |
| 243 |
|
|
| -moz-opacity: 1 |
| 244 |
|
|
| background-attachment: scroll |
| 245 |
|
|
| background-color: transparent |
| 246 |
|
|
| background-image: none |
| 247 |
|
|
| background-position-x: 0% |
| 248 |
|
|
| background-position-y: 0% |
| 249 |
|
|
| background-repeat: repeat |
| 250 |
|
|
| border: 0px none -manakai-default |
| 251 |
|
|
| border-top: 0px none -manakai-default |
| 252 |
|
|
| border-right: 0px none -manakai-default |
| 253 |
|
|
| border-bottom: 0px none -manakai-default |
| 254 |
|
|
| border-left: 0px none -manakai-default |
| 255 |
|
|
| border-bottom-color: -manakai-default |
| 256 |
|
|
| border-bottom-style: none |
| 257 |
|
|
| border-bottom-width: 0px |
| 258 |
|
|
| border-left-color: -manakai-default |
| 259 |
|
|
| border-left-style: none |
| 260 |
|
|
| border-left-width: 0px |
| 261 |
|
|
| border-right-color: -manakai-default |
| 262 |
|
|
| border-right-style: none |
| 263 |
|
|
| border-right-width: 0px |
| 264 |
|
|
| border-top-color: -manakai-default |
| 265 |
|
|
| border-top-style: none |
| 266 |
|
|
| border-top-width: 0px |
| 267 |
|
|
| border-color: -manakai-default |
| 268 |
|
|
| border-style: none |
| 269 |
|
|
| border-width: 0px |
| 270 |
|
|
| float: none |
| 271 |
|
|
| font: @@TODO |
| 272 |
|
|
| list-style: @@TODO |
| 273 |
|
|
| margin: @@TODO |
| 274 |
|
|
| outline-color: invert |
| 275 |
|
|
| outline-style: none |
| 276 |
|
|
| outline-width: 0px |
| 277 |
|
|
| padding: 1]; |
| 278 |
|
|
} |
| 279 |
|
|
|
| 280 |
|
|
sub get_parser () { |
| 281 |
|
|
my $p = Whatpm::CSS::Parser->new; |
| 282 |
|
|
|
| 283 |
|
|
$p->{prop}->{$_} = 1 for (@longhand, @shorthand); |
| 284 |
|
|
$p->{prop_value}->{display}->{$_} = 1 for qw/ |
| 285 |
|
|
block inline inline-block inline-table list-item none |
| 286 |
|
|
table table-caption table-cell table-column table-column-group |
| 287 |
|
|
table-header-group table-footer-group table-row table-row-group |
| 288 |
|
|
/; |
| 289 |
|
|
$p->{prop_value}->{position}->{$_} = 1 for qw/ |
| 290 |
|
|
absolute fixed relative static |
| 291 |
|
|
/; |
| 292 |
|
|
$p->{prop_value}->{float}->{$_} = 1 for qw/ |
| 293 |
|
|
left right none |
| 294 |
|
|
/; |
| 295 |
|
|
$p->{prop_value}->{clear}->{$_} = 1 for qw/ |
| 296 |
|
|
left right none both |
| 297 |
|
|
/; |
| 298 |
|
|
$p->{prop_value}->{direction}->{ltr} = 1; |
| 299 |
|
|
$p->{prop_value}->{direction}->{rtl} = 1; |
| 300 |
|
|
$p->{prop_value}->{'unicode-bidi'}->{$_} = 1 for qw/ |
| 301 |
|
|
normal bidi-override embed |
| 302 |
|
|
/; |
| 303 |
|
|
$p->{prop_value}->{overflow}->{$_} = 1 for qw/ |
| 304 |
|
|
visible hidden scroll auto |
| 305 |
|
|
/; |
| 306 |
|
|
$p->{prop_value}->{visibility}->{$_} = 1 for qw/ |
| 307 |
|
|
visible hidden collapse |
| 308 |
|
|
/; |
| 309 |
|
|
$p->{prop_value}->{'list-style-type'}->{$_} = 1 for qw/ |
| 310 |
|
|
disc circle square decimal decimal-leading-zero |
| 311 |
|
|
lower-roman upper-roman lower-greek lower-latin |
| 312 |
|
|
upper-latin armenian georgian lower-alpha upper-alpha none |
| 313 |
|
|
/; |
| 314 |
|
|
$p->{prop_value}->{'list-style-position'}->{outside} = 1; |
| 315 |
|
|
$p->{prop_value}->{'list-style-position'}->{inside} = 1; |
| 316 |
|
|
$p->{prop_value}->{'page-break-before'}->{$_} = 1 for qw/ |
| 317 |
|
|
auto always avoid left right |
| 318 |
|
|
/; |
| 319 |
|
|
$p->{prop_value}->{'page-break-after'}->{$_} = 1 for qw/ |
| 320 |
|
|
auto always avoid left right |
| 321 |
|
|
/; |
| 322 |
|
|
$p->{prop_value}->{'page-break-inside'}->{auto} = 1; |
| 323 |
|
|
$p->{prop_value}->{'page-break-inside'}->{avoid} = 1; |
| 324 |
|
|
$p->{prop_value}->{'background-repeat'}->{$_} = 1 for qw/ |
| 325 |
|
|
repeat repeat-x repeat-y no-repeat |
| 326 |
|
|
/; |
| 327 |
|
|
$p->{prop_value}->{'background-attachment'}->{scroll} = 1; |
| 328 |
|
|
$p->{prop_value}->{'background-attachment'}->{fixed} = 1; |
| 329 |
|
|
$p->{prop_value}->{'font-style'}->{normal} = 1; |
| 330 |
|
|
$p->{prop_value}->{'font-style'}->{italic} = 1; |
| 331 |
|
|
$p->{prop_value}->{'font-style'}->{oblique} = 1; |
| 332 |
|
|
$p->{prop_value}->{'font-variant'}->{normal} = 1; |
| 333 |
|
|
$p->{prop_value}->{'font-variant'}->{'small-caps'} = 1; |
| 334 |
|
|
$p->{prop_value}->{'text-align'}->{$_} = 1 for qw/ |
| 335 |
|
|
left right center justify begin end |
| 336 |
|
|
/; |
| 337 |
|
|
$p->{prop_value}->{'text-transform'}->{$_} = 1 for qw/ |
| 338 |
|
|
capitalize uppercase lowercase none |
| 339 |
|
|
/; |
| 340 |
|
|
$p->{prop_value}->{'white-space'}->{$_} = 1 for qw/ |
| 341 |
|
|
normal pre nowrap pre-line pre-wrap |
| 342 |
|
|
/; |
| 343 |
|
|
$p->{prop_value}->{'text-decoration'}->{$_} = 1 for qw/ |
| 344 |
|
|
none blink underline overline line-through |
| 345 |
|
|
/; |
| 346 |
|
|
$p->{prop_value}->{'caption-side'}->{$_} = 1 for qw/ |
| 347 |
|
|
top bottom |
| 348 |
|
|
/; |
| 349 |
|
|
$p->{prop_value}->{'table-layout'}->{auto} = 1; |
| 350 |
|
|
$p->{prop_value}->{'table-layout'}->{fixed} = 1; |
| 351 |
|
|
$p->{prop_value}->{'border-collapse'}->{collapase} = 1; |
| 352 |
|
|
$p->{prop_value}->{'border-collapse'}->{separate} = 1; |
| 353 |
|
|
$p->{prop_value}->{'empty-cells'}->{show} = 1; |
| 354 |
|
|
$p->{prop_value}->{'empty-cells'}->{hide} = 1; |
| 355 |
|
|
$p->{prop_value}->{cursor}->{$_} = 1 for qw/ |
| 356 |
|
|
auto crosshair default pointer move e-resize ne-resize nw-resize n-resize |
| 357 |
|
|
se-resize sw-resize s-resize w-resize text wait help progress |
| 358 |
|
|
/; |
| 359 |
|
|
for my $prop (qw/border-top-style border-left-style |
| 360 |
|
|
border-bottom-style border-right-style outline-style/) { |
| 361 |
|
|
$p->{prop_value}->{$prop}->{$_} = 1 for qw/ |
| 362 |
|
|
none hidden dotted dashed solid double groove ridge inset outset |
| 363 |
|
|
/; |
| 364 |
|
|
} |
| 365 |
|
|
for my $prop (qw/color background-color |
| 366 |
|
|
border-bottom-color border-left-color border-right-color |
| 367 |
|
|
border-top-color border-color/) { |
| 368 |
|
|
$p->{prop_value}->{$prop}->{transparent} = 1; |
| 369 |
|
|
$p->{prop_value}->{$prop}->{flavor} = 1; |
| 370 |
|
|
$p->{prop_value}->{$prop}->{'-manakai-default'} = 1; |
| 371 |
|
|
} |
| 372 |
|
|
$p->{prop_value}->{'outline-color'}->{invert} = 1; |
| 373 |
|
|
$p->{prop_value}->{'outline-color'}->{'-manakai-invert-or-currentcolor'} = 1; |
| 374 |
|
|
$p->{pseudo_class}->{$_} = 1 for qw/ |
| 375 |
|
|
active checked disabled empty enabled first-child first-of-type |
| 376 |
|
|
focus hover indeterminate last-child last-of-type link only-child |
| 377 |
|
|
only-of-type root target visited |
| 378 |
|
|
lang nth-child nth-last-child nth-of-type nth-last-of-type not |
| 379 |
|
|
-manakai-contains -manakai-current |
| 380 |
|
|
/; |
| 381 |
|
|
$p->{pseudo_element}->{$_} = 1 for qw/ |
| 382 |
|
|
after before first-letter first-line |
| 383 |
|
|
/; |
| 384 |
|
|
|
| 385 |
|
|
my $css_options = { |
| 386 |
|
|
prop => $p->{prop}, |
| 387 |
|
|
prop_value => $p->{prop_value}, |
| 388 |
|
|
pseudo_class => $p->{pseudo_class}, |
| 389 |
|
|
pseudo_element => $p->{pseudo_element}, |
| 390 |
|
|
}; |
| 391 |
|
|
|
| 392 |
|
|
$p->{href} = 'thismessage:/'; |
| 393 |
|
|
|
| 394 |
|
|
return ($p, $css_options); |
| 395 |
|
|
} # get_parser |
| 396 |
|
|
|
| 397 |
|
|
sub serialize_cssom ($) { |
| 398 |
|
|
my $ss = shift; |
| 399 |
|
|
|
| 400 |
|
|
if (defined $ss) { |
| 401 |
|
|
if ($ss->isa ('Message::IF::CSSStyleSheet')) { |
| 402 |
|
|
my $v = ''; |
| 403 |
|
|
for my $rule (@{$ss->css_rules}) { |
| 404 |
|
|
my $indent = ''; |
| 405 |
|
|
if ($rule->type == $rule->STYLE_RULE) { |
| 406 |
|
|
$v .= '| ' . $indent . '<' . $rule->selector_text . ">\n"; |
| 407 |
|
|
$v .= serialize_style ($rule->style, $indent . ' '); |
| 408 |
|
|
} else { |
| 409 |
|
|
die "Rule type @{[$rule->type]} is not supported"; |
| 410 |
|
|
} |
| 411 |
|
|
} |
| 412 |
|
|
return $v; |
| 413 |
|
|
} else { |
| 414 |
|
|
return '(' . (ref $ss) . ')'; |
| 415 |
|
|
} |
| 416 |
|
|
} else { |
| 417 |
|
|
return '(undef)'; |
| 418 |
|
|
} |
| 419 |
|
|
} # serialize_cssom |
| 420 |
|
|
|
| 421 |
|
|
sub get_computed_style ($$$$$$) { |
| 422 |
|
|
my ($all_test, $doc_id, $selectors, $dom, $css_options, $ss) = @_; |
| 423 |
|
|
|
| 424 |
|
|
my $doc = $all_test->{document}->{$doc_id}->{document}; |
| 425 |
|
|
unless ($doc) { |
| 426 |
|
|
die "Test document $doc_id is not defined"; |
| 427 |
|
|
} |
| 428 |
|
|
|
| 429 |
|
|
my $element = $doc->document_element->query_selector ($selectors); |
| 430 |
|
|
unless ($element) { |
| 431 |
|
|
die "Element $selectors not found in document $doc_id"; |
| 432 |
|
|
} |
| 433 |
|
|
|
| 434 |
|
|
my $window = Message::DOM::Window->___new ($dom); |
| 435 |
|
|
$window->___set_css_options ($css_options); |
| 436 |
|
|
$window->___set_user_style_sheets ([$ss]); |
| 437 |
|
|
$window->set_document ($doc); |
| 438 |
|
|
|
| 439 |
|
|
my $style = $element->current_style; |
| 440 |
|
|
return ($window, $style); |
| 441 |
|
|
} # get_computed_style |
| 442 |
|
|
|
| 443 |
|
|
sub serialize_style ($$) { |
| 444 |
|
|
my ($style, $indent) = @_; |
| 445 |
|
|
|
| 446 |
|
|
## TODO: check @$style |
| 447 |
|
|
|
| 448 |
|
|
my @v; |
| 449 |
|
|
for (map {get_dom_names ($_)} @shorthand, @longhand) { |
| 450 |
|
|
my $dom = $_->[1]; |
| 451 |
|
|
push @v, [$_->[0], $dom, $style->$dom, |
| 452 |
|
|
$style->get_property_priority ($_->[0])]; |
| 453 |
|
|
$v[-1]->[3] = ' !' . $v[-1]->[3] if length $v[-1]->[3]; |
| 454 |
|
|
} |
| 455 |
|
|
return join '', map {"| $indent$_->[0]: $_->[2]$_->[3]\n"} |
| 456 |
|
|
sort {$a->[0] cmp $b->[0]} grep {length $_->[2]} @v; |
| 457 |
|
|
} # serialize_style |
| 458 |
|
|
|
| 459 |
|
|
sub get_dom_names ($) { |
| 460 |
|
|
my $dom_name = $_[0]; |
| 461 |
|
|
if ($_[0] eq 'float') { |
| 462 |
|
|
return ([$_[0] => 'css_float'], [$_[0] => 'style_float']); |
| 463 |
|
|
} |
| 464 |
|
|
|
| 465 |
|
|
$dom_name =~ tr/-/_/; |
| 466 |
|
|
return ([$_[0] => $dom_name]); |
| 467 |
|
|
} # get_dom_names |
| 468 |
|
|
|
| 469 |
|
|
sub apply_diff ($$$) { |
| 470 |
|
|
my ($actual, $expected, $diff) = @_; |
| 471 |
|
|
my @actual = split /[\x0D\x0A]+/, $actual; |
| 472 |
|
|
my @expected = split /[\x0D\x0A]+/, $expected; |
| 473 |
|
|
my @diff = split /[\x0D\x0A]+/, $diff; |
| 474 |
|
|
for (@diff) { |
| 475 |
|
|
if (s/^-//) { |
| 476 |
|
|
push @actual, $_; |
| 477 |
|
|
} elsif (s/^\+//) { |
| 478 |
|
|
push @expected, $_; |
| 479 |
|
|
} else { |
| 480 |
|
|
die "Invalid diff line: $_"; |
| 481 |
|
|
} |
| 482 |
|
|
} |
| 483 |
|
|
$actual = join "\n", sort {$a cmp $b} @actual; |
| 484 |
|
|
$expected = join "\n", sort {$a cmp $b} @expected; |
| 485 |
|
|
($actual, $expected); |
| 486 |
|
|
} # apply_diff |