View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host.css;
16  
17  import org.htmlunit.WebDriverTestCase;
18  import org.htmlunit.junit.BrowserRunner;
19  import org.htmlunit.junit.annotation.Alerts;
20  import org.htmlunit.junit.annotation.HtmlUnitNYI;
21  import org.junit.Test;
22  import org.junit.runner.RunWith;
23  
24  /**
25   * Tests for {@link CSSPageRule}.
26   *
27   * @author Frank Danek
28   * @author Ronald Brill
29   */
30  @RunWith(BrowserRunner.class)
31  public class CSSPageRuleTest extends WebDriverTestCase {
32  
33      /**
34       * @throws Exception if an error occurs
35       */
36      @Test
37      @Alerts("TypeError")
38      public void ctor() throws Exception {
39          final String html = DOCTYPE_HTML
40              + "<html><body>\n"
41              + LOG_TEXTAREA
42              + "<script>\n"
43              + LOG_TEXTAREA_FUNCTION
44              + "try {\n"
45              + "  var rule = new CSSPageRule();\n"
46              + "  log(rule);\n"
47              + "} catch(e) { logEx(e); }\n"
48              + "</script></body></html>";
49  
50          loadPageVerifyTextArea2(html);
51      }
52  
53      /**
54       * @throws Exception if an error occurs
55       */
56      @Test
57      @Alerts({"[object CSSPageRule]", "[object CSSPageRule]"})
58      public void scriptableToString() throws Exception {
59          final String html = DOCTYPE_HTML
60              + "<html><body>\n"
61  
62              + "<style>\n"
63              + "  @page { margin: 1cm; };\n"
64              + "</style>\n"
65  
66              + "<script>\n"
67              + LOG_TITLE_FUNCTION
68              + "  var styleSheet = document.styleSheets[0];\n"
69              + "  var rule = styleSheet.cssRules[0];\n"
70              + "  log(Object.prototype.toString.call(rule));\n"
71              + "  log(rule);\n"
72              + "</script>\n"
73  
74              + "</body></html>";
75  
76          loadPageVerifyTitle2(html);
77      }
78  
79      /**
80       * @throws Exception if an error occurs
81       */
82      @Test
83      @Alerts(DEFAULT = "@page { margin: 1cm; }",
84              FF_ESR = "@page  { margin: 1cm; }")
85      public void cssText() throws Exception {
86          final String html = DOCTYPE_HTML
87              + "<html><body>\n"
88  
89              + LOG_TEXTAREA
90  
91              + "<style>\n"
92              + "  @page { margin: 1cm; }\n"
93              + "</style>\n"
94  
95              + "<script>\n"
96              + LOG_TEXTAREA_FUNCTION
97              + "  var styleSheet = document.styleSheets[0];\n"
98              + "  var rule = styleSheet.cssRules[0];\n"
99              + "  log(rule.cssText);\n"
100             + "</script>\n"
101 
102             + "</body></html>";
103 
104         loadPageVerifyTextArea2(html);
105     }
106 
107     /**
108      * @throws Exception if an error occurs
109      */
110     @Test
111     @Alerts(DEFAULT = "@page { }",
112             FF_ESR = "@page  { }")
113     public void cssTextEmpty() throws Exception {
114         final String html = DOCTYPE_HTML
115             + "<html><body>\n"
116 
117             + LOG_TEXTAREA
118 
119             + "<style>\n"
120             + "  @page { }\n"
121             + "</style>\n"
122 
123             + "<script>\n"
124             + LOG_TEXTAREA_FUNCTION
125             + "  var styleSheet = document.styleSheets[0];\n"
126             + "  var rule = styleSheet.cssRules[0];\n"
127             + "  log(rule.cssText);\n"
128             + "</script>\n"
129 
130             + "</body></html>";
131 
132         loadPageVerifyTextArea2(html);
133     }
134 
135     /**
136      * @throws Exception if an error occurs
137      */
138     @Test
139     @Alerts(DEFAULT = "@page { margin-left: 4cm; margin-right: 3cm; }",
140             FF_ESR = "@page  { margin-left: 4cm; margin-right: 3cm; }")
141     public void cssTextMultipleRules() throws Exception {
142         final String html = DOCTYPE_HTML
143             + "<html><body>\n"
144 
145             + LOG_TEXTAREA
146 
147             + "<style>\n"
148             + "  @page {   margin-left:4cm;margin-right:  3cm; }\n"
149             + "</style>\n"
150 
151             + "<script>\n"
152             + LOG_TEXTAREA_FUNCTION
153             + "  var styleSheet = document.styleSheets[0];\n"
154             + "  var rule = styleSheet.cssRules[0];\n"
155             + "  log(rule.cssText);\n"
156             + "</script>\n"
157 
158             + "</body></html>";
159 
160         loadPageVerifyTextArea2(html);
161     }
162 
163     /**
164      * @throws Exception if an error occurs
165      */
166     @Test
167     @Alerts(DEFAULT = "@page { margin: 1cm; }",
168             FF_ESR = "@page  { margin: 1cm; }")
169     public void cssTextSet() throws Exception {
170         final String html = DOCTYPE_HTML
171             + "<html><body>\n"
172 
173             + LOG_TEXTAREA
174 
175             + "<style>\n"
176             + "  @page { margin: 1cm; }\n"
177             + "</style>\n"
178 
179             + "<script>\n"
180             + LOG_TEXTAREA_FUNCTION
181             + "  var styleSheet = document.styleSheets[0];\n"
182             + "  var rule = styleSheet.cssRules[0];\n"
183             + "  try {"
184             + "    rule.cssText = '@page { margin: 2cm; }';\n"
185             + "    log(rule.cssText);\n"
186             + "  } catch(e) {\n"
187             + "    logEx(e);\n"
188             + "  }\n"
189             + "</script>\n"
190 
191             + "</body></html>";
192 
193         loadPageVerifyTextArea2(html);
194     }
195 
196     /**
197      * @throws Exception if an error occurs
198      */
199     @Test
200     @Alerts("null")
201     public void parentRule() throws Exception {
202         final String html = DOCTYPE_HTML
203             + "<html><body>\n"
204 
205             + "<style>\n"
206             + "  @page { margin: 1cm; }\n"
207             + "</style>\n"
208 
209             + "<script>\n"
210             + LOG_TITLE_FUNCTION
211             + "  var styleSheet = document.styleSheets[0];\n"
212             + "  var rule = styleSheet.cssRules[0];\n"
213             + "  log(rule.parentRule);\n"
214             + "</script>\n"
215 
216             + "</body></html>";
217 
218         loadPageVerifyTitle2(html);
219     }
220 
221     /**
222      * @throws Exception if an error occurs
223      */
224     @Test
225     @Alerts("null")
226     public void parentRuleSet() throws Exception {
227         final String html = DOCTYPE_HTML
228             + "<html><body>\n"
229 
230             + "<style>\n"
231             + "  @page { margin: 1cm; }\n"
232             + "</style>\n"
233 
234             + "<script>\n"
235             + LOG_TITLE_FUNCTION
236             + "  var styleSheet = document.styleSheets[0];\n"
237             + "  var rule = styleSheet.cssRules[0];\n"
238             + "  try {"
239             + "    rule.parentRule = rule;\n"
240             + "    log(rule.parentRule);\n"
241             + "  } catch(e) {\n"
242             + "    logEx(e);\n"
243             + "  }\n"
244             + "</script>\n"
245 
246             + "</body></html>";
247 
248         loadPageVerifyTitle2(html);
249     }
250 
251     /**
252      * @throws Exception if an error occurs
253      */
254     @Test
255     @Alerts("[object CSSStyleSheet]")
256     public void parentStyleSheet() throws Exception {
257         final String html = DOCTYPE_HTML
258             + "<html><body>\n"
259 
260             + "<style>\n"
261             + "  @page { margin: 1cm; }\n"
262             + "</style>\n"
263 
264             + "<script>\n"
265             + LOG_TITLE_FUNCTION
266             + "  var styleSheet = document.styleSheets[0];\n"
267             + "  var rule = styleSheet.cssRules[0];\n"
268             + "  log(rule.parentStyleSheet);\n"
269             + "</script>\n"
270 
271             + "</body></html>";
272 
273         loadPageVerifyTitle2(html);
274     }
275 
276     /**
277      * @throws Exception if an error occurs
278      */
279     @Test
280     @Alerts("[object CSSStyleSheet]")
281     public void parentStyleSheetSet() throws Exception {
282         final String html = DOCTYPE_HTML
283             + "<html><body>\n"
284 
285             + "<style>\n"
286             + "  @page { margin: 1cm; }\n"
287             + "</style>\n"
288 
289             + "<script>\n"
290             + LOG_TITLE_FUNCTION
291             + "  var styleSheet = document.styleSheets[0];\n"
292             + "  var rule = styleSheet.cssRules[0];\n"
293             + "  try {"
294             + "    rule.parentStyleSheet = null;\n"
295             + "    log(rule.parentStyleSheet);\n"
296             + "  } catch(e) {\n"
297             + "    logEx(e);\n"
298             + "  }\n"
299             + "</script>\n"
300 
301             + "</body></html>";
302 
303         loadPageVerifyTitle2(html);
304     }
305 
306     /**
307      * @throws Exception if an error occurs
308      */
309     @Test
310     @Alerts("")
311     public void selectorTextEmpty() throws Exception {
312         final String html = DOCTYPE_HTML
313             + "<html><body>\n"
314 
315             + "<style>\n"
316             + "  @page { margin: 1cm; }\n"
317             + "</style>\n"
318 
319             + "<script>\n"
320             + LOG_TITLE_FUNCTION
321             + "  var styleSheet = document.styleSheets[0];\n"
322             + "  var rule = styleSheet.cssRules[0];\n"
323             + "  try {"
324             + "    log(rule.selectorText);\n"
325             + "  } catch(e) {\n"
326             + "    logEx(e);\n"
327             + "  }\n"
328             + "</script>\n"
329 
330             + "</body></html>";
331 
332         loadPageVerifyTitle2(html);
333     }
334 
335     /**
336      * @throws Exception if an error occurs
337      */
338     @Test
339     @Alerts(":first")
340     public void selectorText() throws Exception {
341         final String html = DOCTYPE_HTML
342             + "<html><body>\n"
343 
344             + "<style>\n"
345             + "  @page :first { margin: 1cm; }\n"
346             + "</style>\n"
347 
348             + "<script>\n"
349             + LOG_TITLE_FUNCTION
350             + "  var styleSheet = document.styleSheets[0];\n"
351             + "  var rule = styleSheet.cssRules[0];\n"
352             + "  try {"
353             + "    log(rule.selectorText);\n"
354             + "  } catch(e) {\n"
355             + "    logEx(e);\n"
356             + "  }\n"
357             + "</script>\n"
358 
359             + "</body></html>";
360 
361         loadPageVerifyTitle2(html);
362     }
363 
364     /**
365      * @throws Exception if an error occurs
366      */
367     @Test
368     @Alerts(":first")
369     public void selectorTextCaseInsensitive() throws Exception {
370         final String html = DOCTYPE_HTML
371             + "<html><body>\n"
372 
373             + "<style>\n"
374             + "  @page :FiRsT { margin: 1cm; }\n"
375             + "</style>\n"
376 
377             + "<script>\n"
378             + LOG_TITLE_FUNCTION
379             + "  var styleSheet = document.styleSheets[0];\n"
380             + "  var rule = styleSheet.cssRules[0];\n"
381             + "  try {"
382             + "    log(rule.selectorText);\n"
383             + "  } catch(e) {\n"
384             + "    logEx(e);\n"
385             + "  }\n"
386             + "</script>\n"
387 
388             + "</body></html>";
389 
390         loadPageVerifyTitle2(html);
391     }
392 
393     /**
394      * @throws Exception if an error occurs
395      */
396     @Test
397     @Alerts({":first", ":left"})
398     public void selectorTextSet() throws Exception {
399         final String html = DOCTYPE_HTML
400             + "<html><body>\n"
401 
402             + "<style>\n"
403             + "  @page :first { margin: 1cm; }\n"
404             + "</style>\n"
405 
406             + "<script>\n"
407             + LOG_TITLE_FUNCTION
408             + "  var styleSheet = document.styleSheets[0];\n"
409             + "  var rule = styleSheet.cssRules[0];\n"
410             + "  try {"
411             + "    log(rule.selectorText);\n"
412             + "    rule.selectorText = ':left';\n"
413             + "    log(rule.selectorText);\n"
414             + "  } catch(e) {\n"
415             + "    logEx(e);\n"
416             + "  }\n"
417             + "</script>\n"
418 
419             + "</body></html>";
420 
421         loadPageVerifyTitle2(html);
422     }
423 
424     /**
425      * @throws Exception if an error occurs
426      */
427     @Test
428     @Alerts({":first", "null"})
429     public void selectorTextSetNull() throws Exception {
430         final String html = DOCTYPE_HTML
431             + "<html><body>\n"
432 
433             + "<style>\n"
434             + "  @page :first { margin: 1cm; }\n"
435             + "</style>\n"
436 
437             + "<script>\n"
438             + LOG_TITLE_FUNCTION
439             + "  var styleSheet = document.styleSheets[0];\n"
440             + "  var rule = styleSheet.cssRules[0];\n"
441             + "  try {"
442             + "    log(rule.selectorText);\n"
443             + "    rule.selectorText = null;\n"
444             + "    log(rule.selectorText);\n"
445             + "  } catch(e) {\n"
446             + "    logEx(e);\n"
447             + "  }\n"
448             + "</script>\n"
449 
450             + "</body></html>";
451 
452         loadPageVerifyTitle2(html);
453     }
454 
455     /**
456      * @throws Exception if an error occurs
457      */
458     @Test
459     @Alerts({":first", ""})
460     public void selectorTextSetEmpty() throws Exception {
461         final String html = DOCTYPE_HTML
462             + "<html><body>\n"
463 
464             + "<style>\n"
465             + "  @page :first { margin: 1cm; }\n"
466             + "</style>\n"
467 
468             + "<script>\n"
469             + LOG_TITLE_FUNCTION
470             + "  var styleSheet = document.styleSheets[0];\n"
471             + "  var rule = styleSheet.cssRules[0];\n"
472             + "  try {"
473             + "    log(rule.selectorText);\n"
474             + "    rule.selectorText = '';\n"
475             + "    log(rule.selectorText);\n"
476             + "  } catch(e) {\n"
477             + "    logEx(e);\n"
478             + "  }\n"
479             + "</script>\n"
480 
481             + "</body></html>";
482 
483         loadPageVerifyTitle2(html);
484     }
485 
486     /**
487      * @throws Exception if an error occurs
488      */
489     @Test
490     @Alerts({":first", ":first"})
491     public void selectorTextSetInvalid() throws Exception {
492         final String html = DOCTYPE_HTML
493             + "<html><body>\n"
494 
495             + "<style>\n"
496             + "  @page :first { margin: 1cm; }\n"
497             + "</style>\n"
498 
499             + "<script>\n"
500             + LOG_TITLE_FUNCTION
501             + "  var styleSheet = document.styleSheets[0];\n"
502             + "  var rule = styleSheet.cssRules[0];\n"
503             + "  try {"
504             + "    log(rule.selectorText);\n"
505             + "    rule.selectorText = ':grey';\n"
506             + "    log(rule.selectorText);\n"
507             + "  } catch(e) {\n"
508             + "    logEx(e);\n"
509             + "  }\n"
510             + "</script>\n"
511 
512             + "</body></html>";
513 
514         loadPageVerifyTitle2(html);
515     }
516 
517     /**
518      * @throws Exception if an error occurs
519      */
520     @Test
521     @Alerts({":first", ":left"})
522     public void selectorTextSetCaseInsensitive() throws Exception {
523         final String html = DOCTYPE_HTML
524             + "<html><body>\n"
525 
526             + "<style>\n"
527             + "  @page :first { margin: 1cm; }\n"
528             + "</style>\n"
529 
530             + "<script>\n"
531             + LOG_TITLE_FUNCTION
532             + "  var styleSheet = document.styleSheets[0];\n"
533             + "  var rule = styleSheet.cssRules[0];\n"
534             + "  try {"
535             + "    log(rule.selectorText);\n"
536             + "    rule.selectorText = ':LeFt';\n"
537             + "    log(rule.selectorText);\n"
538             + "  } catch(e) {\n"
539             + "    logEx(e);\n"
540             + "  }\n"
541             + "</script>\n"
542 
543             + "</body></html>";
544 
545         loadPageVerifyTitle2(html);
546     }
547 
548     /**
549      * @throws Exception if an error occurs
550      */
551     @Test
552     @Alerts(DEFAULT = {"[object CSSStyleDeclaration]", "[object CSSStyleDeclaration]", "4", "[object CSSPageRule]",
553                        "margin: 1cm;",
554                        "string margin-top",
555                        "string margin-right",
556                        "string margin-bottom",
557                        "string margin-left"},
558             FF = {"[object CSSPageDescriptors]", "[object CSSPageDescriptors]", "4", "[object CSSPageRule]",
559                   "margin: 1cm;",
560                   "string margin-top",
561                   "string margin-right",
562                   "string margin-bottom",
563                   "string margin-left"},
564             FF_ESR = {"[object CSS2Properties]", "[object CSS2Properties]", "4", "[object CSSPageRule]",
565                       "margin: 1cm;",
566                       "string margin-top",
567                       "string margin-right",
568                       "string margin-bottom",
569                       "string margin-left"})
570     @HtmlUnitNYI(CHROME = {"[object CSSStyleDeclaration]", "[object CSSStyleDeclaration]",
571                            "1", "[object CSSPageRule]", "margin: 1cm;", "string margin: 1cm"},
572             EDGE = {"[object CSSStyleDeclaration]", "[object CSSStyleDeclaration]",
573                     "1", "[object CSSPageRule]", "margin: 1cm;", "string margin: 1cm"},
574             FF = {"[object CSSStyleDeclaration]", "[object CSSStyleDeclaration]",
575                   "1", "[object CSSPageRule]", "margin: 1cm;", "string margin: 1cm"},
576             FF_ESR = {"[object CSSStyleDeclaration]", "[object CSSStyleDeclaration]",
577                       "1", "[object CSSPageRule]", "margin: 1cm;", "string margin: 1cm"})
578     // FIXME FF returns CSS2Properties vs. default returns CSSStyleDeclaration :(
579     public void style() throws Exception {
580         final String html = DOCTYPE_HTML
581             + "<html><body>\n"
582 
583             + "<style>\n"
584             + "  @page { margin: 1cm; }\n"
585             + "</style>\n"
586 
587             + "<script>\n"
588             + LOG_TITLE_FUNCTION
589             + "  var styleSheet = document.styleSheets[0];\n"
590             + "  var rule = styleSheet.cssRules[0];\n"
591             + "  var style = rule.style;\n"
592             + "  log(Object.prototype.toString.call(style));\n"
593             + "  log(style);\n"
594             + "  log(style.length);\n"
595             + "  log(style.parentRule);\n"
596             + "  log(style.cssText);\n"
597             + "  for (var i = 0; i < style.length; i++) {\n"
598             + "    log(typeof style.item(i) + ' ' + style.item(i));\n"
599             + "  }\n"
600             + "</script>\n"
601 
602             + "</body></html>";
603 
604         loadPageVerifyTitle2(html);
605     }
606 
607     /**
608      * @throws Exception if an error occurs
609      */
610     @Test
611     @Alerts(DEFAULT = {"[object CSSStyleDeclaration]", "[object CSSStyleDeclaration]", "0", "[object CSSPageRule]", ""},
612             FF = {"[object CSSPageDescriptors]", "[object CSSPageDescriptors]", "0", "[object CSSPageRule]", ""},
613             FF_ESR = {"[object CSS2Properties]", "[object CSS2Properties]", "0", "[object CSSPageRule]", ""})
614     @HtmlUnitNYI(FF = {"[object CSSStyleDeclaration]", "[object CSSStyleDeclaration]", "0", "[object CSSPageRule]", ""},
615             FF_ESR = {"[object CSSStyleDeclaration]", "[object CSSStyleDeclaration]", "0", "[object CSSPageRule]", ""})
616     public void styleEmpty() throws Exception {
617         final String html = DOCTYPE_HTML
618             + "<html><body>\n"
619 
620             + "<style>\n"
621             + "  @page { }\n"
622             + "</style>\n"
623 
624             + "<script>\n"
625             + LOG_TITLE_FUNCTION
626             + "  var styleSheet = document.styleSheets[0];\n"
627             + "  var rule = styleSheet.cssRules[0];\n"
628             + "  var style = rule.style;\n"
629             + "  log(Object.prototype.toString.call(style));\n"
630             + "  log(style);\n"
631             + "  log(style.length);\n"
632             + "  log(style.parentRule);\n"
633             + "  log(style.cssText);\n"
634             + "  for (var i = 0; i < style.length; i++) {\n"
635             + "    log(style.item(i));\n"
636             + "  }\n"
637             + "</script>\n"
638 
639             + "</body></html>";
640 
641         loadPageVerifyTitle2(html);
642     }
643 }