com.gargoylesoftware.htmlunit.javascript.host.css.CSSStyleSheetTest.java Source code

Java tutorial

Introduction

Here is the source code for com.gargoylesoftware.htmlunit.javascript.host.css.CSSStyleSheetTest.java

Source

/*
 * Copyright (c) 2002-2016 Gargoyle Software Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.gargoylesoftware.htmlunit.javascript.host.css;

import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.CHROME;
import static com.gargoylesoftware.htmlunit.BrowserRunner.Browser.IE;

import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

import com.gargoylesoftware.htmlunit.BrowserRunner;
import com.gargoylesoftware.htmlunit.BrowserRunner.Alerts;
import com.gargoylesoftware.htmlunit.BrowserRunner.NotYetImplemented;
import com.gargoylesoftware.htmlunit.MockWebConnection;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebDriverTestCase;
import com.gargoylesoftware.htmlunit.html.HtmlPageTest;
import com.gargoylesoftware.htmlunit.util.NameValuePair;

/**
 * Unit tests for {@link CSSStyleSheet}.
 *
 * @author Marc Guillemot
 * @author Ahmed Ashour
 * @author Frank Danek
 * @author Ronald Brill
 */
@RunWith(BrowserRunner.class)
public class CSSStyleSheetTest extends WebDriverTestCase {

    /**
     * @throws Exception on test failure
     */
    @Test
    @Alerts(DEFAULT = { "[object CSSStyleSheet]", "[object HTMLStyleElement]", "true", "undefined",
            "false" }, IE = { "[object CSSStyleSheet]", "[object HTMLStyleElement]", "true",
                    "[object HTMLStyleElement]", "true" })
    public void owningNodeOwningElement() throws Exception {
        final String html = "<html><head><title>test_hasChildNodes</title>\n" + "<script>\n" + "function test(){\n"
                + "  var myStyle = document.getElementById('myStyle');\n"
                + "  var stylesheet = document.styleSheets[0];\n" + "  alert(stylesheet);\n"
                + "  alert(stylesheet.ownerNode);\n" + "  alert(stylesheet.ownerNode == myStyle);\n"
                + "  alert(stylesheet.owningElement);\n" + "  alert(stylesheet.owningElement == myStyle);\n" + "}\n"
                + "</script>\n" + "<style id='myStyle' type='text/css'></style>\n"
                + "</head><body onload='test()'>\n" + "</body></html>";
        loadPageWithAlerts2(html);
    }

    /**
     * @throws Exception on test failure
     */
    @Test
    @Alerts(DEFAULT = { "4", "0", "1", "2", "3", "length", "item" }, FF38 = { "4", "0", "1", "2", "3", "item",
            "length" })
    public void rules() throws Exception {
        final String html = "<html><head><title>First</title>\n" + "<style>\n"
                + "  BODY { background-color: white; color: black; }\n" + "  H1 { font: 8pt Arial bold; }\n"
                + "  P  { font: 10pt Arial; text-indent: 0.5in; }\n"
                + "  A  { text-decoration: none; color: blue; }\n" + "</style>\n" + "<script>\n"
                + "  function test(){\n" + "    var rules;\n" + "    if (document.styleSheets[0].cssRules)\n"
                + "      rules = document.styleSheets[0].cssRules;\n" + "    else\n"
                + "      rules = document.styleSheets[0].rules;\n" + "    alert(rules.length);\n"
                + "    for (var i in rules)\n" + "      alert(i);\n" + "  }\n" + "</script>\n"
                + "</head><body onload='test()'>\n" + "</body></html>";
        loadPageWithAlerts2(html);
    }

    /**
     * Test for bug 2063012 (missing href attribute).
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "4", "URLstyle2.css", "URLstyle4.css", "null", "null" })
    public void href() throws Exception {
        final String baseUrl = getDefaultUrl().toExternalForm();
        final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + "<html>\n" + "  <head>\n" + "    <link href='"
                + baseUrl + "style1.css' type='text/css'></link>\n" + "    <link href='" + baseUrl
                + "style2.css' rel='stylesheet'></link>\n" + "    <link href='" + baseUrl + "style3.css'></link>\n"
                + "    <link href='style4.css' rel='stylesheet'></link>\n"
                + "    <style>div.x { color: red; }</style>\n" + "  </head>\n" + "  <body>\n"
                + "    <style>div.y { color: green; }</style>\n" + "    <script>\n"
                + "      alert(document.styleSheets.length);\n"
                + "      for (i = 0; i < document.styleSheets.length; i++) {\n"
                + "        alert(document.styleSheets[i].href);\n" + "      }\n" + "    </script>\n" + "  </body>\n"
                + "</html>";

        final MockWebConnection conn = getMockWebConnection();
        conn.setResponse(new URL(getDefaultUrl(), "style1.css"), "", "text/css");
        conn.setResponse(new URL(getDefaultUrl(), "style2.css"), "", "text/css");
        conn.setResponse(new URL(getDefaultUrl(), "style3.css"), "", "text/css");
        conn.setResponse(new URL(getDefaultUrl(), "style4.css"), "", "text/css");

        loadPageWithAlerts2(html, new URL(getDefaultUrl(), "test.html"));
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "8", "URLstyle1.css 1", "URLstyle2.css 0", "URLstyle3.css 0",
            "URLstyle4.css 1", "URLstyle5.css 1", "URLstyle6.css 0",
            "URLstyle7.css 0",
            "URLstyle8.css 1" }, IE = { "2", "URLstyle1.css 1", "URLstyle5.css 1" })
    @NotYetImplemented
    public void hrefWrongContentType() throws Exception {
        final String baseUrl = getDefaultUrl().toExternalForm();
        final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + "<html>\n" + "  <head>\n" + "    <link href='"
                + baseUrl + "style1.css' rel='stylesheet' type='text/css'></link>\n" + "    <link href='" + baseUrl
                + "style2.css' rel='stylesheet' type='text/css'></link>\n" + "    <link href='" + baseUrl
                + "style3.css' rel='stylesheet' type='text/css'></link>\n" + "    <link href='" + baseUrl
                + "style4.css' rel='stylesheet' type='text/css'></link>\n" + "    <link href='" + baseUrl
                + "style5.css' rel='stylesheet' ></link>\n" + "    <link href='" + baseUrl
                + "style6.css' rel='stylesheet' ></link>\n" + "    <link href='" + baseUrl
                + "style7.css' rel='stylesheet' ></link>\n" + "    <link href='" + baseUrl
                + "style8.css' rel='stylesheet' ></link>\n" + "  </head>\n" + "  <body>\n" + "    <script>\n"
                + "      alert(document.styleSheets.length);\n"
                + "      for (i = 0; i < document.styleSheets.length; i++) {\n"
                + "        var sheet = document.styleSheets[i];\n"
                + "        alert(sheet.href + ' ' + sheet.cssRules.length);\n" + "      }\n" + "    </script>\n"
                + "  </body>\n" + "</html>";

        final MockWebConnection conn = getMockWebConnection();
        conn.setResponse(new URL(getDefaultUrl(), "style1.css"), "div { color: red; }", "text/css");
        conn.setResponse(new URL(getDefaultUrl(), "style2.css"), "div { color: red; }", "text/html");
        conn.setResponse(new URL(getDefaultUrl(), "style3.css"), "div { color: red; }", "text/plain");
        conn.setResponse(new URL(getDefaultUrl(), "style4.css"), "div { color: red; }", "");
        conn.setResponse(new URL(getDefaultUrl(), "style5.css"), "div { color: red; }", "text/css");
        conn.setResponse(new URL(getDefaultUrl(), "style6.css"), "div { color: red; }", "text/html");
        conn.setResponse(new URL(getDefaultUrl(), "style7.css"), "div { color: red; }", "text/plain");
        conn.setResponse(new URL(getDefaultUrl(), "style8.css"), "div { color: red; }", "");

        loadPageWithAlerts2(html, new URL(getDefaultUrl(), "test.html"));
    }

    /**
     * Minimal test for addRule / insertRule.
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "1", "false", "false", "0", "2", "p" }, FF = { "1", "false", "true", "0", "2", "p" })
    public void addRule_insertRule() throws Exception {
        final String html = "<html><head><title>foo</title><script>\n" + "function doTest() {\n"
                + "  var f = document.getElementById('myStyle');\n"
                + "  var s = f.sheet ? f.sheet : f.styleSheet;\n" + "  var rules = s.cssRules || s.rules;\n"
                + "  alert(rules.length);\n" + "  alert(s.insertRule == undefined);\n"
                + "  alert(s.addRule == undefined);\n" + "  if (s.insertRule)\n"
                + "    alert(s.insertRule('div { color: red; }', 0));\n" + "  else\n"
                + "    alert(s.addRule('div', 'color: red;', 1));\n" + "  alert(rules.length);\n"
                + "  alert(rules[1].selectorText);\n" + "}</script>\n"
                + "<style id='myStyle'>p { vertical-align:top }</style>\n" + "</head><body onload='doTest()'>\n"
                + "</body></html>";

        loadPageWithAlerts2(html);
    }

    /**
     * Minimal test for removeRule / deleteRule.
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "2", "false", "false", "undefined", "1", "div" }, FF = { "2", "false", "true", "undefined",
            "1", "div" })
    public void removeRule_deleteRule() throws Exception {
        final String html = "<html><head><title>foo</title><script>\n" + "function doTest() {\n"
                + "  var f = document.getElementById('myStyle');\n"
                + "  var s = f.sheet ? f.sheet : f.styleSheet;\n" + "  var rules = s.cssRules || s.rules;\n"
                + "  alert(rules.length);\n" + "  alert(s.deleteRule == undefined);\n"
                + "  alert(s.removeRule == undefined);\n" + "  if (s.deleteRule)\n"
                + "    alert(s.deleteRule(0));\n" + "  else\n" + "    alert(s.removeRule(0));\n"
                + "  alert(rules.length);\n" + "  alert(rules[0].selectorText);\n" + "}</script>\n"
                + "<style id='myStyle'>p { vertical-align:top } div { color: red; }</style>\n"
                + "</head><body onload='doTest()'>\n" + "</body></html>";

        loadPageWithAlerts2(html);
    }

    /**
     * Test that exception handling in insertRule.
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts("exception")
    public void deleteRuleInvalidParam() throws Exception {
        final String html = "<html><head><title>foo</title><script>\n" + "function doTest() {\n"
                + "  var f = document.getElementById('myStyle');\n"
                + "  var s = f.sheet ? f.sheet : f.styleSheet;\n" + "  var rules = s.cssRules || s.rules;\n"
                + "  try {\n" + "    if (s.deleteRule)\n" + "      s.deleteRule(19);\n" + "    else\n"
                + "      s.removeRule(19);\n" + "    alert('deleted');\n"
                + "  } catch(err) { alert('exception'); }\n" + "}</script>\n" + "<style id='myStyle'></style>\n"
                + "</head><body onload='doTest()'>\n" + "</body></html>";

        loadPageWithAlerts2(html);
    }

    /**
     * Test that CSSParser can handle leading whitespace in insertRule.
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "2", ".testStyleDef", ".testStyle" })
    public void insertRuleLeadingWhitespace() throws Exception {
        final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + "<html><head><title>foo</title><script>\n"
                + "function doTest() {\n" + "  var f = document.getElementById('myStyle');\n"
                + "  var s = f.sheet ? f.sheet : f.styleSheet;\n" + "  var rules = s.cssRules || s.rules;\n"
                + "  if (s.insertRule) {\n" + "    s.insertRule('.testStyle { width: 24px; }', 0);\n"
                + "    s.insertRule(' .testStyleDef { height: 42px; }', 0);\n" + "    alert(rules.length);\n"
                + "    alert(rules[0].selectorText);\n" + "    alert(rules[1].selectorText);\n" + "  }\n"
                + "}</script>\n" + "<style id='myStyle'></style>\n" + "</head><body onload='doTest()'>\n"
                + "</body></html>";

        loadPageWithAlerts2(html);
    }

    /**
     * Test that exception handling in insertRule.
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts("exception")
    public void insertInvalidRule() throws Exception {
        final String html = "<html><head><title>foo</title><script>\n" + "function doTest() {\n"
                + "  var f = document.getElementById('myStyle');\n"
                + "  var s = f.sheet ? f.sheet : f.styleSheet;\n" + "  var rules = s.cssRules || s.rules;\n"
                + "  try {\n" + "    if (s.insertRule)\n" + "      s.insertRule('.testStyle1', 0);\n" + "    else\n"
                + "      s.addRule('.testStyle1;', '', 1);\n" + "    alert('inserted');\n"
                + "  } catch(err) { alert('exception'); }\n" + "}</script>\n" + "<style id='myStyle'></style>\n"
                + "</head><body onload='doTest()'>\n" + "</body></html>";

        loadPageWithAlerts2(html);
    }

    /**
     * @throws Exception on test failure
     */
    @Test
    @Alerts(DEFAULT = { "false", "false", "true", "true", "false" }, CHROME = { "false", "false", "false", "false",
            "false" })
    @NotYetImplemented(CHROME)
    public void langCondition() throws Exception {
        final String htmlSnippet = "<div id='elt2' lang='en'></div>\n" + "  <div id='elt3' lang='en-GB'></div>\n"
                + "  <div id='elt4' lang='english'></div>\n";
        doTest(":lang(en)", htmlSnippet);
    }

    /**
     * @throws Exception on test failure
     */
    @Test
    @Alerts(DEFAULT = { "false", "false", "true", "false", "true" }, CHROME = { "false", "false", "false", "false",
            "false" })
    @NotYetImplemented(CHROME)
    public void langConditionParent() throws Exception {
        final String htmlSnippet = "<div id='elt2' lang='en'>\n" + "  <div id='elt3' lang='de'></div>\n"
                + "  <div id='elt4' ></div>\n" + "</div>\n";
        doTest(":lang(en)", htmlSnippet);
    }

    /**
     * @throws Exception on test failure
     */
    @Test
    @Alerts(DEFAULT = { "true", "false" }, CHROME = { "false", "false" })
    @NotYetImplemented(CHROME)
    public void css2_root() throws Exception {
        doTest(":root", "");
    }

    /**
     * CSS3 pseudo selector :not is not yet supported.
     * @throws Exception on test failure
     */
    @Test
    @Alerts(DEFAULT = { "true", "true", "false" }, CHROME = { "false", "false", "false" })
    @NotYetImplemented(CHROME)
    public void css3_not() throws Exception {
        doTest(":not(span)", "<span id='elt2'></span>");
    }

    /**
     * @throws Exception on test failure
     */
    @Test
    @Alerts(DEFAULT = { "false", "false", "true", "false", "true", "true", "true", "true" }, CHROME = { "false",
            "false", "false", "false", "false", "false", "false", "false" })
    @NotYetImplemented(CHROME)
    public void css3_enabled() throws Exception {
        final String htmlSnippet = "<input id='elt2'>\n" + "<input id='elt3' disabled>\n"
                + "<input id='elt4' type='checkbox'>\n" + "<button id='elt5' ></button>\n"
                + "<select id='elt6' ></select>" + "<textarea id='elt7' ></textarea>\n";
        doTest(":enabled", htmlSnippet);
    }

    /**
     * @throws Exception on test failure
     */
    @Test
    @Alerts(DEFAULT = { "false", "false", "true", "false", "true", "true", "true", "true" }, CHROME = { "false",
            "false", "false", "false", "false", "false", "false", "false" })
    @NotYetImplemented(CHROME)
    public void css3_disabled() throws Exception {
        final String htmlSnippet = "<input id='elt2' disabled>\n" + "<input id='elt3'>\n"
                + "<input id='elt4' type='checkbox' disabled>\n" + "<button id='elt5' disabled></button>\n"
                + "<select id='elt6' disabled></select>" + "<textarea id='elt7' disabled></textarea>\n";
        doTest(":disabled", htmlSnippet);
    }

    /**
     * @throws Exception on test failure
     */
    @Test
    @Alerts(DEFAULT = { "false", "false", "false", "false", "true", "false", "true", "false" }, CHROME = { "false",
            "false", "false", "false", "false", "false", "false", "false" })
    @NotYetImplemented(CHROME)
    public void css3_checked() throws Exception {
        final String htmlSnippet = "<input id='elt2'>\n" + "<input id='elt3' checked>\n"
                + "<input id='elt4' type='checkbox' checked>\n" + "<input id='elt5' type='checkbox'>\n"
                + "<input id='elt6' type='radio' checked>\n" + "<input id='elt7' type='radio'>\n";
        doTest(":checked", htmlSnippet);
    }

    private void doTest(final String cssSelector, final String htmlSnippet) throws Exception {
        final String html = "<html id='elt0'><head><title>First</title>\n" + "<style>\n" + cssSelector
                + " { z-index: 10 }\n" + "</style>\n" + "<script>\n" + "  function test(){\n"
                + "    var getStyle = function(e) {\n"
                + "      return window.getComputedStyle ? window.getComputedStyle(e,'') : e.currentStyle; };\n"
                + "    var i = 0;\n" + "    while (true) {\n"
                + "      var elt = document.getElementById('elt' + i++);\n" + "      if (!elt) return;\n"
                + "      alert(getStyle(elt).zIndex == 10);\n" + "    }\n" + "  }\n" + "</script>\n"
                + "</head><body onload='test()'>\n" + "  <div id='elt1'></div>\n" + htmlSnippet + "</body></html>";
        loadPageWithAlerts2(html);
    }

    /**
     * Test for handling priority !important.
     * @see <a href="http://sf.net/support/tracker.php?aid=2880057">Bug 2880057</a>
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts("width=100")
    public void important() throws Exception {
        final String html = "<html><head><title>foo</title><script>\n" + "function doTest() {\n"
                + "  var e = document.getElementById('style1');\n" + "  alert('width=' + e.clientWidth);\n" + "}\n"
                + "</script>\n" + "<style>\n" + "#style1 {left: 25px; width: 100px !important;}\n"
                + "#style1 {position: absolute; left: 100px; width: 50px; height: 50px;}\n" + "</style>\n"
                + "</head><body onload='doTest()'>\n" + "<div id='style1'>Hello</div>" + "</body></html>";

        loadPageWithAlerts2(html);
    }

    /**
     * Test for handling/ignoring @font-face.
     * see bug 2984265
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts("none")
    public void fontFace() throws Exception {
        final String html = "<html><head><title>foo</title><script>\n" + "function doTest() {\n"
                + "  var e = document.getElementById('div1');\n"
                + "  var s = window.getComputedStyle ? window.getComputedStyle(e,'') : e.currentStyle;\n"
                + "  alert(s.display);\n" + "}\n" + "</script>\n" + "<style>\n"
                + "  @font-face { font-family: YanoneKaffeesatz; src: url(/YanoneKaffeesatz-Regular.otf); }\n"
                + "  body { font-family: YanoneKaffeesatz; }\n" + "  div { display: none; }\n" + "</style>\n"
                + "</head><body onload='doTest()'>\n" + "<div id='div1'>invisible</div>" + "visible"
                + "</body></html>";

        loadPageWithAlerts2(html);
    }

    /**
     * Test that the rule with higher specificity wins.
     * @throws Exception on test failure
     */
    @Test
    @Alerts(DEFAULT = "60", CHROME = "auto")
    @NotYetImplemented(CHROME)
    public void rulePriority_specificity() throws Exception {
        final String html = "<html><head>\n" + "<style>\n" + "div { z-index: 60 }\n" + "* { z-index: 10 }\n"
                + "</style></head>\n" + "<body>\n" + "<div id='it'>hello</div>\n" + "<script>\n"
                + "var getStyle = function(e) {\n"
                + "return window.getComputedStyle ? window.getComputedStyle(e,'') : e.currentStyle;\n" + "};\n"
                + "alert(getStyle(document.getElementById('it')).zIndex);\n" + "</script>\n" + "</body></html>";

        loadPageWithAlerts2(html);
    }

    /**
     * Test that the rule with higher specificity wins. More complete case.
     * @throws Exception on test failure
     */
    @Test
    @Alerts(DEFAULT = "60", CHROME = "auto")
    @NotYetImplemented(CHROME)
    public void rulePriority_specificity2() throws Exception {
        final String html = "<html><head>\n" + "<style>\n" + ".classA .classB .classC { z-index: 60 }\n"
                + ".classA .classC { z-index: 10 }\n" + "</style></head>\n" + "<body>\n" + "<div class='classA'>\n"
                + "<div class='classB'>\n" + "<div id='it' class='classC'>hello</div>\n" + "</div>\n" + "</div>\n"
                + "<script>\n" + "var getStyle = function(e) {\n"
                + "return window.getComputedStyle ? window.getComputedStyle(e,'') : e.currentStyle;\n" + "};\n"
                + "alert(getStyle(document.getElementById('it')).zIndex);\n" + "</script>\n" + "</body></html>";

        loadPageWithAlerts2(html);
    }

    /**
     * Test that the last one wins when selectors have the same specificity.
     * @throws Exception on test failure
     */
    @Test
    @Alerts(DEFAULT = { "10", "10" }, CHROME = { "auto", "auto" })
    @NotYetImplemented(CHROME)
    public void rulePriority_position() throws Exception {
        final String html = "<html><head>\n" + "<style>\n" + ".classA { z-index: 60 }\n"
                + ".classB { z-index: 10 }\n" + "</style></head>\n" + "<body>\n"
                + "<div id='it1' class='classA classB'>hello</div>\n"
                + "<div id='it2' class='classA classB'>hello</div>\n" + "<script>\n"
                + "var getStyle = function(e) {\n"
                + "return window.getComputedStyle ? window.getComputedStyle(e,'') : e.currentStyle;\n" + "};\n"
                + "alert(getStyle(document.getElementById('it1')).zIndex);\n"
                + "alert(getStyle(document.getElementById('it2')).zIndex);\n" + "</script>\n" + "</body></html>";

        loadPageWithAlerts2(html);
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaOnStyleTag_noMedia() throws Exception {
        mediaOnStyleTag("");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaOnStyleTag_whitespace() throws Exception {
        mediaOnStyleTag(" ");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaOnStyleTag_all() throws Exception {
        mediaOnStyleTag("all");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaOnStyleTag_screen() throws Exception {
        mediaOnStyleTag("screen");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "block", "1" })
    public void mediaOnStyleTag_print() throws Exception {
        mediaOnStyleTag("print");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaOnStyleTag_print_not() throws Exception {
        mediaOnStyleTag("not print");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaOnStyleTag_multipleWithScreen() throws Exception {
        mediaOnStyleTag("print, screen, tv");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "block", "1" })
    public void mediaOnStyleTag_multipleWithoutScreen() throws Exception {
        mediaOnStyleTag("print, projection, tv");
    }

    private void mediaOnStyleTag(final String media) throws Exception {
        final String html = "<html><head>\n" + "<style media='" + media + "'> div { display: none }</style>\n"
                + "</head><body>\n" + "<div id='d'>hello</div>\n" + "<script>\n"
                + "  var getStyle = function(e) {\n"
                + "    return window.getComputedStyle ? window.getComputedStyle(e,'') : e.currentStyle;\n"
                + "  };\n" + "  alert(getStyle(document.getElementById('d')).display);\n"
                + "  alert(document.styleSheets.length);\n" + "</script></body></html>";
        loadPageWithAlerts2(html);
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaOnLinkTag_noMedia() throws Exception {
        mediaOnLinkTag("");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaOnLinkTag_whitespace() throws Exception {
        mediaOnLinkTag(" ");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaOnLinkTag_all() throws Exception {
        mediaOnLinkTag("all");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaOnLinkTag_screen() throws Exception {
        mediaOnLinkTag("screen");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "block", "1" }, CHROME = { "block", "0" })
    public void mediaOnLinkTag_notScreen() throws Exception {
        mediaOnLinkTag("print");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaOnLinkTag_multipleWithScreen() throws Exception {
        mediaOnLinkTag("print, screen, tv");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "block", "1" }, CHROME = { "block", "0" })
    public void mediaOnLinkTag_multipleWithoutScreen() throws Exception {
        mediaOnLinkTag("print, projection, tv");
    }

    private void mediaOnLinkTag(final String media) throws Exception {
        final String html = "<html><head>\n" + "<link rel='stylesheet' media='" + media + "' href='" + URL_SECOND
                + "'></link>\n" + "</head><body>\n" + "<div id='d'>hello</div>\n" + "<script>\n"
                + "  var getStyle = function(e) {\n"
                + "    return window.getComputedStyle ? window.getComputedStyle(e,'') : e.currentStyle;\n"
                + "  };\n" + "  alert(getStyle(document.getElementById('d')).display);\n"
                + "  alert(document.styleSheets.length);\n" + "</script></body></html>";

        getMockWebConnection().setResponse(URL_SECOND, "div { display: none }", "text/css");
        loadPageWithAlerts2(html);
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaRule_screen() throws Exception {
        mediaRule("screen");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "block", "1" })
    public void mediaRule_notScreen() throws Exception {
        mediaRule("print");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaRule_multipleWithScreen() throws Exception {
        mediaRule("print, screen, tv");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "block", "1" })
    public void mediaRule_multipleWithoutScreen() throws Exception {
        mediaRule("print, projection, tv");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "block", "1" }, IE = { "none", "1" })
    @NotYetImplemented(IE)
    public void mediaRule_max_width() throws Exception {
        mediaRule("screen and (max-width: 123px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaRule_max_width_match() throws Exception {
        mediaRule("screen and (max-width: 10000px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "block", "1" })
    public void mediaRule_min_width() throws Exception {
        mediaRule("screen and (min-width: 10000px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "none", "1" }, IE = { "block", "1" })
    @NotYetImplemented(IE)
    public void mediaRule_min_width_match() throws Exception {
        mediaRule("screen and (min-width: 123px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "block", "1" })
    public void mediaRule_max_device_width() throws Exception {
        mediaRule("screen and (max-device-width: 123px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaRule_max_device_width_match() throws Exception {
        mediaRule("screen and (max-device-width: 10000px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "block", "1" })
    public void mediaRule_min_device_width() throws Exception {
        mediaRule("screen and (min-device-width: 10000px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaRule_min_device_width_match() throws Exception {
        mediaRule("screen and (min-device-width: 123px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "block", "1" }, IE = { "none", "1" })
    @NotYetImplemented(IE)
    public void mediaRule_max_height() throws Exception {
        mediaRule("screen and (max-height: 123px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaRule_max_height_match() throws Exception {
        mediaRule("screen and (max-height: 10000px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "block", "1" })
    public void mediaRule_min_height() throws Exception {
        mediaRule("screen and (min-height: 10000px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "none", "1" }, IE = { "block", "1" })
    @NotYetImplemented(IE)
    public void mediaRule_min_height_match() throws Exception {
        mediaRule("screen and (min-height: 123px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "block", "1" })
    public void mediaRule_max_device_height() throws Exception {
        mediaRule("screen and (max-device-height: 123px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaRule_max_device_height_match() throws Exception {
        mediaRule("screen and (max-device-height: 10000px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "block", "1" })
    public void mediaRule_min_device_height() throws Exception {
        mediaRule("screen and (min-device-height: 10000px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaRule_min_device_height_match() throws Exception {
        mediaRule("screen and (min-device-height: 123px)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "block", "1" })
    public void mediaRule_resolution() throws Exception {
        mediaRule("screen and (resolution: 4dpi)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "none", "1" }, IE = { "block", "1" })
    @NotYetImplemented(IE)
    public void mediaRule_resolution_match() throws Exception {
        mediaRule("screen and (resolution: 96dpi)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "block", "1" }, IE = { "none", "1" })
    @NotYetImplemented(IE)
    public void mediaRule_max_resolution() throws Exception {
        mediaRule("screen and (max-resolution: 90dpi)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "none", "1" })
    public void mediaRule_max_resolution_match() throws Exception {
        mediaRule("screen and (max-resolution: 10000dpi)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "block", "1" })
    public void mediaRule_min_resolution() throws Exception {
        mediaRule("screen and (min-resolution: 10000dpi)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "none", "1" }, IE = { "block", "1" })
    @NotYetImplemented(IE)
    public void mediaRule_min_resolution_match() throws Exception {
        mediaRule("screen and (min-resolution: 10dpi)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "block", "1" }, IE = { "none", "1" })
    @NotYetImplemented(IE)
    public void mediaRule_portrait() throws Exception {
        mediaRule("screen and (orientation: portrait)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "none", "1" }, IE = { "block", "1" })
    @NotYetImplemented(IE)
    public void mediaRule_portrait_not() throws Exception {
        mediaRule("not screen and (orientation: portrait)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "none", "1" }, IE = { "block", "1" })
    @NotYetImplemented(IE)
    public void mediaRule_landscape() throws Exception {
        mediaRule("screen and (orientation: landscape)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts(DEFAULT = { "block", "1" }, IE = { "none", "1" })
    @NotYetImplemented(IE)
    public void mediaRule_landscape_not() throws Exception {
        mediaRule("not screen and (orientation: landscape)");
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts({ "block", "1" })
    public void mediaRule_invalidOrientation() throws Exception {
        mediaRule("screen and (orientation: unknown)");
    }

    private void mediaRule(final String media) throws Exception {
        final String html = HtmlPageTest.STANDARDS_MODE_PREFIX_ + "<html>\n" + "<head>\n" + "  <style> @media "
                + media + " { div { display: none } }</style>\n" + "</head>\n" + "<body>\n"
                + "  <div id='d'>hello</div>\n" + "  <script>\n" + "    var getStyle = function(e) {\n"
                + "      return window.getComputedStyle ? window.getComputedStyle(e,'') : e.currentStyle;\n"
                + "    };\n" + "    alert(getStyle(document.getElementById('d')).display);\n"
                + "    alert(document.styleSheets.length);\n" + "  </script>\n" + "</body></html>";
        loadPageWithAlerts2(html);
    }

    @SuppressWarnings("unchecked")
    private static <T> T get(final Object o, final Class<?> c, final String fieldName) {
        try {
            final Field field = c.getDeclaredField(fieldName);
            field.setAccessible(true);
            return (T) field.get(o);
        } catch (final Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * @throws Exception if an error occurs
     */
    @Test
    @Alerts("rgb(255, 0, 0)")
    public void veryBig() throws Exception {
        getWebDriver();

        int maxInMemory = 0;
        final WebClient webClient = get(this, WebDriverTestCase.class, "webClient_");
        if (webClient != null) {
            maxInMemory = webClient.getOptions().getMaxInMemory();
        }

        final String baseUrl = getDefaultUrl().toExternalForm();
        final String html = "<html>\n" + "  <head>\n" + "    <link href='" + baseUrl
                + "style.css' rel='stylesheet'></link>\n" + "  </head>\n" + "  <body>\n"
                + "    <a href='second.html'>second page</a>\n" + "  </body>\n" + "</html>";

        final String html2 = "<html>\n" + "  <head>\n" + "    <link href='" + baseUrl
                + "style.css' rel='stylesheet'></link>\n" + "  </head>\n" + "  <body class='someRed'>\n"
                + "    <script>\n" + "      var getStyle = function(e) {\n"
                + "        return window.getComputedStyle ? window.getComputedStyle(e,'') : e.currentStyle;\n"
                + "      };\n" + "      alert(getStyle(document.body).color);\n" + "    </script>\n" + "  </body>\n"
                + "</html>";

        final MockWebConnection conn = getMockWebConnection();
        final List<NameValuePair> headers2 = new ArrayList<>();
        headers2.add(new NameValuePair("Last-Modified", "Sun, 15 Jul 2007 20:46:27 GMT"));
        final String bigContent = ".someRed { color: red; }" + StringUtils.repeat(' ', maxInMemory);
        conn.setResponse(new URL(getDefaultUrl(), "style2.css"), bigContent, 200, "OK", "text/html", headers2);
        conn.setResponse(new URL(getDefaultUrl(), "second.html"), html2);

        final List<NameValuePair> headers1 = new ArrayList<>();
        headers1.add(new NameValuePair("Location", "style2.css"));
        conn.setResponse(new URL(getDefaultUrl(), "style.css"), "", 302, "Moved", "text/html", headers1);

        final WebDriver driver = loadPage2(html, new URL(getDefaultUrl(), "test.html"));
        driver.findElement(By.linkText("second page")).click();
        verifyAlerts(driver, getExpectedAlerts());
    }

}