1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.htmlunit.javascript.host.css;
16
17 import org.htmlunit.BrowserVersion;
18 import org.htmlunit.SimpleWebTestCase;
19 import org.htmlunit.css.ComputedCssStyleDeclaration;
20 import org.htmlunit.css.CssStyleSheet;
21 import org.htmlunit.cssparser.parser.CSSErrorHandler;
22 import org.htmlunit.cssparser.parser.CSSException;
23 import org.htmlunit.cssparser.parser.CSSOMParser;
24 import org.htmlunit.cssparser.parser.CSSParseException;
25 import org.htmlunit.cssparser.parser.javacc.CSS3Parser;
26 import org.htmlunit.cssparser.parser.selector.Selector;
27 import org.htmlunit.cssparser.parser.selector.SelectorList;
28 import org.htmlunit.cssparser.parser.selector.SelectorListImpl;
29 import org.htmlunit.html.DomElement;
30 import org.htmlunit.html.HtmlElement;
31 import org.htmlunit.html.HtmlForm;
32 import org.htmlunit.html.HtmlInput;
33 import org.htmlunit.html.HtmlPage;
34 import org.htmlunit.html.HtmlStyle;
35 import org.htmlunit.javascript.host.html.HTMLStyleElement;
36 import org.htmlunit.junit.annotation.Alerts;
37 import org.junit.jupiter.api.Test;
38 import org.w3c.dom.NodeList;
39
40
41
42
43
44
45
46
47
48 public class CSSStyleSheet2Test extends SimpleWebTestCase {
49
50
51
52
53 @Test
54 public void selects_miscSelectors() throws Exception {
55 final String html = DOCTYPE_HTML
56 + "<html><head><title>test</title>\n"
57 + "</head><body><style></style>\n"
58 + "<form name='f1' action='foo' class='yui-log'>\n"
59 + "<div><div><input name='i1' id='m1'></div></div>\n"
60 + "<input name='i2' class='yui-log'>\n"
61 + "<button name='b1' class='yui-log'>\n"
62 + "<button name='b2'>\n"
63 + "</form>\n"
64 + "</body></html>";
65
66 final HtmlPage page = loadPage(html);
67 final HtmlElement body = page.getBody();
68 final HtmlForm form = page.getFormByName("f1");
69 final HtmlInput input1 = (HtmlInput) page.getElementsByName("i1").get(0);
70 final HtmlInput input2 = (HtmlInput) page.getElementsByName("i2").get(0);
71 final DomElement button1 = page.getElementsByName("b1").get(0);
72 final DomElement button2 = page.getElementsByName("b2").get(0);
73 final BrowserVersion browserVersion = getBrowserVersion();
74
75 final HtmlStyle node = (HtmlStyle) page.getElementsByTagName("style").item(0);
76 final HTMLStyleElement host = (HTMLStyleElement) node.getScriptableObject();
77 final CSSStyleSheet sheet = host.getSheet();
78
79 Selector selector = parseSelector(sheet, "*.yui-log input");
80
81 assertFalse(CssStyleSheet.selects(browserVersion, selector, body, null, false, true));
82 assertFalse(CssStyleSheet.selects(browserVersion, selector, form, null, false, true));
83 assertTrue(CssStyleSheet.selects(browserVersion, selector, input1, null, false, true));
84 assertTrue(CssStyleSheet.selects(browserVersion, selector, input2, null, false, true));
85 assertFalse(CssStyleSheet.selects(browserVersion, selector, button1, null, false, true));
86 assertFalse(CssStyleSheet.selects(browserVersion, selector, button2, null, false, true));
87
88 selector = parseSelector(sheet, "#m1");
89 assertTrue(CssStyleSheet.selects(browserVersion, selector, input1, null, false, true));
90 assertFalse(CssStyleSheet.selects(browserVersion, selector, input2, null, false, true));
91 }
92
93 private static Selector parseSelector(final CSSStyleSheet sheet, final String rule) throws Exception {
94 return parseSelectors(rule).get(0);
95 }
96
97 private static SelectorList parseSelectors(final String source) throws Exception {
98 SelectorList selectors;
99 final CSSErrorHandler errorHandler = new CSSErrorHandler() {
100
101 @Override
102 public void warning(final CSSParseException exception) throws CSSException {
103 throw exception;
104 }
105
106 @Override
107 public void fatalError(final CSSParseException exception) throws CSSException {
108 throw exception;
109 }
110
111 @Override
112 public void error(final CSSParseException exception) throws CSSException {
113 throw exception;
114 }
115 };
116 final CSSOMParser parser = new CSSOMParser(new CSS3Parser());
117 parser.setErrorHandler(errorHandler);
118 selectors = parser.parseSelectors(source);
119
120 if (null == selectors) {
121 selectors = new SelectorListImpl();
122 }
123 return selectors;
124 }
125
126
127
128
129 @Test
130 public void selects_anyNodeSelector() throws Exception {
131 testSelects("*", true, true, true);
132 }
133
134
135
136
137 @Test
138 public void selects_childSelector() throws Exception {
139 testSelects("body > div", false, true, false);
140 }
141
142
143
144
145 @Test
146 public void selects_descendantSelector() throws Exception {
147 testSelects("body span", false, false, true);
148 }
149
150
151
152
153 @Test
154 public void selects_elementSelector() throws Exception {
155 testSelects("div", false, true, false);
156 }
157
158
159
160
161 @Test
162 public void selects_directAdjacentSelector() throws Exception {
163 testSelects("span + span", false, false, true);
164 }
165
166
167
168
169 @Test
170 public void selects_conditionalSelector_idCondition() throws Exception {
171 testSelects("span#s", false, false, true);
172 testSelects("#s", false, false, true);
173 testSelects("span[id=s]", false, false, true);
174 }
175
176
177
178
179 @Test
180 public void selectsIdConditionWithSpecialChars() throws Exception {
181 final String html = DOCTYPE_HTML
182 + "<html><body><style></style>\n"
183 + "<div id='d:e'></div>\n"
184 + "<div id='d-e'></div>\n"
185 + "</body></html>";
186 final HtmlPage page = loadPage(html);
187 final BrowserVersion browserVersion = getBrowserVersion();
188
189 Selector selector = parseSelectors("#d\\:e").get(0);
190 assertTrue(CssStyleSheet.selects(browserVersion, selector, page.getHtmlElementById("d:e"), null, false, true));
191
192 selector = parseSelectors("#d-e").get(0);
193 assertTrue(CssStyleSheet.selects(browserVersion, selector, page.getHtmlElementById("d-e"), null, false, true));
194 }
195
196
197
198
199 @Test
200 public void selects_conditionalSelector_classCondition() throws Exception {
201 testSelects("div.bar", false, true, false);
202 testSelects(".bar", false, true, false);
203 testSelects("div[class~=bar]", false, true, false);
204 }
205
206
207
208
209 @Test
210 public void selects_pseudoClass_root() throws Exception {
211 testSelects(":root", false, false, false);
212 }
213
214
215
216
217 @Test
218 public void selects_pseudoClass_lang() throws Exception {
219 testSelects(":lang(en)", false, true, true);
220 testSelects(":lang(de)", false, false, false);
221 }
222
223
224
225
226 @Test
227 public void selects_pseudoClass_negation() throws Exception {
228 testSelects(":not(div)", true, false, true);
229 }
230
231 private void testSelects(final String css, final boolean selectBody, final boolean selectDivD,
232 final boolean selectSpanS) throws Exception {
233 final String html = DOCTYPE_HTML
234 + "<html>\n"
235 + " <body id='b'>\n"
236 + " <style></style>\n"
237 + " <div id='d' class='foo bar' lang='en-GB'>\n"
238 + " <span>x</span>\n"
239 + " <span id='s'>a</span>b\n"
240 + " </div>\n"
241 + " </body>\n"
242 + "</html>";
243 final HtmlPage page = loadPage(html);
244 final BrowserVersion browserVersion = getBrowserVersion();
245
246 final Selector selector = parseSelectors(css).get(0);
247 assertEquals(selectBody,
248 CssStyleSheet.selects(browserVersion, selector, page.getHtmlElementById("b"), null, false, true));
249 assertEquals(selectDivD,
250 CssStyleSheet.selects(browserVersion, selector, page.getHtmlElementById("d"), null, false, true));
251 assertEquals(selectSpanS,
252 CssStyleSheet.selects(browserVersion, selector, page.getHtmlElementById("s"), null, false, true));
253 }
254
255
256
257
258
259 @Test
260 @Alerts("ComputedCssStyleDeclaration for 'HtmlBody[<body>]'")
261 public void brokenExternalCSS() throws Exception {
262 final String html = "<html><head>\n"
263 + "<link rel='stylesheet' type='text/css' href='" + URL_SECOND + "'/></head></html>";
264
265 getMockWebConnection().setResponse(URL_SECOND, "body { font-weight: 900\\9; }");
266 final HtmlPage htmlPage = loadPage(html);
267
268 final NodeList list = htmlPage.getElementsByTagName("body");
269 final HtmlElement element = (HtmlElement) list.item(0);
270 final ComputedCssStyleDeclaration style = htmlPage.getEnclosingWindow().getComputedStyle(element, null);
271 assertEquals(getExpectedAlerts()[0], style.toString());
272 }
273 }