View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.html;
18  
19  import static org.apache.juneau.TestUtils.*;
20  import static org.junit.jupiter.api.Assertions.*;
21  
22  import java.util.*;
23  import java.util.function.*;
24  import java.util.stream.*;
25  
26  import org.apache.juneau.*;
27  import org.apache.juneau.html.annotation.*;
28  import org.apache.juneau.internal.*;
29  import org.apache.juneau.reflect.*;
30  import org.apache.juneau.svl.*;
31  import org.junit.jupiter.api.*;
32  
33  /**
34   * Tests the @HtmlDocConfig annotation.
35   */
36  class HtmlDocConfigAnnotation_Test extends TestBase {
37  
38  	private static void check(String expected, Object o) {
39  		assertEquals(expected, TO_STRING.apply(o));
40  	}
41  
42  	private static final Function<Object,String> TO_STRING = t -> {
43  		if (isArray(t))
44  			return HtmlDocConfigAnnotation_Test.TO_STRING.apply(ArrayUtils.toList(t, Object.class));
45  		if (t instanceof Collection)
46  			return ((Collection<?>)t)
47  				.stream()
48  				.map(HtmlDocConfigAnnotation_Test.TO_STRING)
49  				.collect(Collectors.joining(","));
50  		if (t instanceof HtmlDocTemplate)
51  			return t.getClass().getSimpleName();
52  		return t.toString();
53  	};
54  
55  	static VarResolverSession sr = VarResolver.create().vars(XVar.class).build().createSession();
56  
57  	//-----------------------------------------------------------------------------------------------------------------
58  	// Basic tests
59  	//-----------------------------------------------------------------------------------------------------------------
60  
61  	@HtmlDocConfig(
62  		aside="$X{foo}",
63  		footer="$X{foo}",
64  		head="$X{foo}",
65  		header="$X{foo}",
66  		nav="$X{foo}",
67  		navlinks="$X{foo1}",
68  		noResultsMessage="$X{foo}",
69  		nowrap="$X{true}",
70  		script="$X{foo1}",
71  		style="$X{foo1}",
72  		stylesheet="$X{foo1}",
73  		template=BasicHtmlDocTemplate.class
74  	)
75  	static class A {}
76  	static ClassInfo a = ClassInfo.of(A.class);
77  
78  	@Test void basic() {
79  		var al = AnnotationWorkList.of(sr, a.getAnnotationList());
80  		var x = HtmlDocSerializer.create().apply(al).build().getSession();
81  		check("foo", x.getAside());
82  		check("foo", x.getFooter());
83  		check("foo", x.getHead());
84  		check("foo", x.getHeader());
85  		check("foo", x.getNav());
86  		check("foo1", x.getNavlinks());
87  		check("foo", x.getNoResultsMessage());
88  		check("true", x.isNowrap());
89  		check("foo1", x.getScript());
90  		check("foo1", x.getStyle());
91  		check("foo1", x.getStylesheet());
92  		check("BasicHtmlDocTemplate", x.getTemplate());
93  	}
94  
95  	//-----------------------------------------------------------------------------------------------------------------
96  	// Annotation with no values.
97  	//-----------------------------------------------------------------------------------------------------------------
98  
99  	@HtmlDocConfig()
100 	static class B {}
101 	static ClassInfo b = ClassInfo.of(B.class);
102 
103 	@Test void defaults() {
104 		var al = AnnotationWorkList.of(sr, b.getAnnotationList());
105 		var x = HtmlDocSerializer.create().apply(al).build().getSession();
106 		check("", x.getAside());
107 		check("", x.getFooter());
108 		check("", x.getHead());
109 		check("", x.getHeader());
110 		check("", x.getNav());
111 		check("", x.getNavlinks());
112 		check("<p>no results</p>", x.getNoResultsMessage());
113 		check("false", x.isNowrap());
114 		check("", x.getScript());
115 		check("", x.getStyle());
116 		check("", x.getStylesheet());
117 		check("BasicHtmlDocTemplate", x.getTemplate());
118 	}
119 
120 	//-----------------------------------------------------------------------------------------------------------------
121 	// No annotation.
122 	//-----------------------------------------------------------------------------------------------------------------
123 
124 	static class C {}
125 	static ClassInfo c = ClassInfo.of(C.class);
126 
127 	@Test void noAnnotation() {
128 		var al = AnnotationWorkList.of(sr, c.getAnnotationList());
129 		var x = HtmlDocSerializer.create().apply(al).build().getSession();
130 		check("", x.getAside());
131 		check("", x.getFooter());
132 		check("", x.getHead());
133 		check("", x.getHeader());
134 		check("", x.getNav());
135 		check("", x.getNavlinks());
136 		check("<p>no results</p>", x.getNoResultsMessage());
137 		check("false", x.isNowrap());
138 		check("", x.getScript());
139 		check("", x.getStyle());
140 		check("", x.getStylesheet());
141 		check("BasicHtmlDocTemplate", x.getTemplate());
142 	}
143 
144 	//-----------------------------------------------------------------------------------------------------------------
145 	// Inheritance tests
146 	//-----------------------------------------------------------------------------------------------------------------
147 
148 	@HtmlDocConfig(
149 		aside={"$X{foo2}","$X{INHERIT}"},
150 		footer={"$X{foo2}","$X{INHERIT}"},
151 		head={"$X{foo2}","$X{INHERIT}"},
152 		header={"$X{foo2}","$X{INHERIT}"},
153 		nav={"$X{foo2}","$X{INHERIT}"},
154 		navlinks={"$X{foo2}","$X{INHERIT}"},
155 		script={"$X{foo2}","$X{INHERIT}"},
156 		style={"$X{foo2}","$X{INHERIT}"},
157 		stylesheet={"$X{foo2}","$X{INHERIT}"}
158 	)
159 	static class D1 extends A {}
160 	static ClassInfo d1 = ClassInfo.of(D1.class);
161 
162 	@Test void inheritance1() {
163 		var al = AnnotationWorkList.of(sr, d1.getAnnotationList());
164 		var x = HtmlDocSerializer.create().apply(al).build().getSession();
165 		check("foo2,foo", x.getAside());
166 		check("foo2,foo", x.getFooter());
167 		check("foo2,foo", x.getHead());
168 		check("foo2,foo", x.getHeader());
169 		check("foo2,foo", x.getNav());
170 		check("foo2,foo1", x.getNavlinks());
171 		check("foo2,foo1", x.getScript());
172 		check("foo2,foo1", x.getStyle());
173 		check("foo2,foo1", x.getStylesheet());
174 	}
175 
176 	@HtmlDocConfig(
177 		aside={"$X{INHERIT}","$X{foo2}"},
178 		footer={"$X{INHERIT}","$X{foo2}"},
179 		head={"$X{INHERIT}","$X{foo2}"},
180 		header={"$X{INHERIT}","$X{foo2}"},
181 		nav={"$X{INHERIT}","$X{foo2}"},
182 		navlinks={"$X{INHERIT}","$X{foo2}"},
183 		script={"$X{INHERIT}","$X{foo2}"},
184 		style={"$X{INHERIT}","$X{foo2}"},
185 		stylesheet={"$X{INHERIT}","$X{foo2}"}
186 	)
187 	static class D2 extends A {}
188 	static ClassInfo d2 = ClassInfo.of(D2.class);
189 
190 	@Test void inheritance2() {
191 		var al = AnnotationWorkList.of(sr, d2.getAnnotationList());
192 		var x = HtmlDocSerializer.create().apply(al).build().getSession();
193 		check("foo,foo2", x.getAside());
194 		check("foo,foo2", x.getFooter());
195 		check("foo,foo2", x.getHead());
196 		check("foo,foo2", x.getHeader());
197 		check("foo,foo2", x.getNav());
198 		check("foo1,foo2", x.getNavlinks());
199 		check("foo1,foo2", x.getScript());
200 		check("foo1,foo2", x.getStyle());
201 		check("foo1,foo2", x.getStylesheet());
202 	}
203 
204 	@HtmlDocConfig(
205 		aside={"$X{foo2}"},
206 		footer={"$X{foo2}"},
207 		head={"$X{foo2}"},
208 		header={"$X{foo2}"},
209 		nav={"$X{foo2}"},
210 		navlinks={"$X{foo2}"},
211 		script={"$X{foo2}"},
212 		style={"$X{foo2}"},
213 		stylesheet={"$X{foo2}"}
214 	)
215 	static class D3 extends A {}
216 	static ClassInfo d3 = ClassInfo.of(D3.class);
217 
218 	@Test void inheritance3() {
219 		var al = AnnotationWorkList.of(sr, d3.getAnnotationList());
220 		var x = HtmlDocSerializer.create().apply(al).build().getSession();
221 		check("foo2", x.getAside());
222 		check("foo2", x.getFooter());
223 		check("foo2", x.getHead());
224 		check("foo2", x.getHeader());
225 		check("foo2", x.getNav());
226 		check("foo2", x.getNavlinks());
227 		check("foo2", x.getScript());
228 		check("foo2", x.getStyle());
229 		check("foo2", x.getStylesheet());
230 	}
231 
232 	@HtmlDocConfig(
233 		aside={"NONE"},
234 		footer={"NONE"},
235 		head={"NONE"},
236 		header={"NONE"},
237 		nav={"NONE"},
238 		navlinks={"NONE"},
239 		script={"NONE"},
240 		style={"NONE"},
241 		stylesheet={"NONE"}
242 	)
243 	static class D4 extends A {}
244 	static ClassInfo d4 = ClassInfo.of(D4.class);
245 
246 	@Test void inheritance4() {
247 		var al = AnnotationWorkList.of(sr, d4.getAnnotationList());
248 		var x = HtmlDocSerializer.create().apply(al).build().getSession();
249 		check("", x.getAside());
250 		check("", x.getFooter());
251 		check("", x.getHead());
252 		check("", x.getHeader());
253 		check("", x.getNav());
254 		check("", x.getNavlinks());
255 		check("", x.getScript());
256 		check("", x.getStyle());
257 		check("", x.getStylesheet());
258 	}
259 
260 	//-----------------------------------------------------------------------------------------------------------------
261 	// Widgets
262 	//-----------------------------------------------------------------------------------------------------------------
263 
264 	@HtmlDocConfig(
265 		aside="$W{E}",
266 		footer="$W{E}",
267 		head="$W{E}",
268 		header="$W{E}",
269 		nav="$W{E}",
270 		navlinks="$W{E}",
271 		noResultsMessage="$W{E}",
272 		nowrap="$W{E}",
273 		script="$W{E}",
274 		style="$W{E}",
275 		stylesheet="$W{E}",
276 		widgets=EWidget.class
277 	)
278 	static class E {}
279 	static ClassInfo e = ClassInfo.of(E.class);
280 
281 	public static class EWidget implements HtmlWidget {
282 		@Override
283 		public String getName() {
284 			return "E";
285 		}
286 		@Override
287 		public String getHtml(VarResolverSession session) {
288 			return "xxx";
289 		}
290 		@Override
291 		public String getScript(VarResolverSession session) {
292 			return "yyy";
293 		}
294 		@Override
295 		public String getStyle(VarResolverSession session) {
296 			return "zzz";
297 		}
298 	}
299 
300 	@Test void widgets_basic() {
301 		var al = AnnotationWorkList.of(sr, e.getAnnotationList());
302 		var x = HtmlDocSerializer.create().apply(al).build().getSession();
303 		check("$W{E}", x.getAside());
304 		check("$W{E}", x.getFooter());
305 		check("$W{E}", x.getHead());
306 		check("$W{E}", x.getHeader());
307 		check("$W{E}", x.getNav());
308 		check("$W{E}", x.getNavlinks());
309 		check("$W{E}", x.getNoResultsMessage());
310 		check("false", x.isNowrap());
311 		check("$W{E}", x.getScript());
312 		check("$W{E}", x.getStyle());
313 		check("$W{E}", x.getStylesheet());
314 		check("BasicHtmlDocTemplate", x.getTemplate());
315 	}
316 
317 	@Test void widgets_resolution() throws Exception {
318 		var al = AnnotationWorkList.of(sr, e.getAnnotationList());
319 		var x = HtmlDocSerializer.create().apply(al).build().getSession();
320 		var r = x.serialize(null).replaceAll("[\r\n]+", "|");
321 		assertContainsAll(r, "<aside>xxx</aside>","<footer>xxx</footer>","<head>xxx","<style>@import \"xxx\"; xxx zzz</style>","<nav><ol><li>xxx</li></ol>xxx</nav>","<script>xxx| yyy|</script>");
322 	}
323 
324 	//-----------------------------------------------------------------------------------------------------------------
325 	// Rank sorting
326 	//-----------------------------------------------------------------------------------------------------------------
327 
328 	@HtmlDocConfig(
329 		rank=1,
330 		aside="f1"
331 	)
332 	static class F1 {}
333 
334 	@HtmlDocConfig(
335 		aside="f2"
336 	)
337 	static class F2 extends F1 {}
338 
339 	@HtmlDocConfig(
340 		rank=3,
341 		aside="f3"
342 	)
343 	static class F3 extends F2 {}
344 
345 	@HtmlDocConfig(
346 		rank=2,
347 		aside="f4"
348 	)
349 	static class F4 extends F3 {}
350 
351 	@HtmlDocConfig(
352 		rank=3,
353 		aside="f5"
354 	)
355 	static class F5 extends F4 {}
356 
357 	static ClassInfo f1 = ClassInfo.of(F1.class);
358 	static ClassInfo f2 = ClassInfo.of(F2.class);
359 	static ClassInfo f3 = ClassInfo.of(F3.class);
360 	static ClassInfo f4 = ClassInfo.of(F4.class);
361 	static ClassInfo f5 = ClassInfo.of(F5.class);
362 
363 	@Test void e01_rankedAnnotations_f1() {
364 		var al = AnnotationWorkList.of(sr, f1.getAnnotationList());
365 		var x = HtmlDocSerializer.create().apply(al).build().getSession();
366 		check("f1", x.getAside());
367 	}
368 
369 	@Test void e02_rankedAnnotations_f2() {
370 		var al = AnnotationWorkList.of(sr, f2.getAnnotationList());
371 		var x = HtmlDocSerializer.create().apply(al).build().getSession();
372 		check("f1", x.getAside());
373 	}
374 
375 	@Test void e03_rankedAnnotations_f3() {
376 		var al = AnnotationWorkList.of(sr, f3.getAnnotationList());
377 		var x = HtmlDocSerializer.create().apply(al).build().getSession();
378 		check("f3", x.getAside());
379 	}
380 
381 	@Test void e04_rankedAnnotations_f4() {
382 		var al = AnnotationWorkList.of(sr, f4.getAnnotationList());
383 		var x = HtmlDocSerializer.create().apply(al).build().getSession();
384 		check("f3", x.getAside());
385 	}
386 
387 	@Test void e05_rankedAnnotations_f5() {
388 		var al = AnnotationWorkList.of(sr, f5.getAnnotationList());
389 		var x = HtmlDocSerializer.create().apply(al).build().getSession();
390 		check("f5", x.getAside());
391 	}
392 }