View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.doxia.siterenderer;
20  
21  import java.io.File;
22  import java.util.ArrayList;
23  import java.util.Iterator;
24  import java.util.List;
25  
26  import org.htmlunit.BrowserVersion;
27  import org.htmlunit.CollectingAlertHandler;
28  import org.htmlunit.WebClient;
29  import org.htmlunit.html.DomElement;
30  import org.htmlunit.html.DomNodeList;
31  import org.htmlunit.html.HtmlAnchor;
32  import org.htmlunit.html.HtmlElement;
33  import org.htmlunit.html.HtmlHeading1;
34  import org.htmlunit.html.HtmlMain;
35  import org.htmlunit.html.HtmlPage;
36  import org.htmlunit.html.HtmlSection;
37  
38  import static org.codehaus.plexus.testing.PlexusExtension.getTestFile;
39  import static org.junit.jupiter.api.Assertions.assertEquals;
40  import static org.junit.jupiter.api.Assertions.assertNotNull;
41  import static org.junit.jupiter.api.Assertions.assertTrue;
42  
43  /**
44   * Verify client side rendering of Mermaid diagrams.
45   */
46  public class MermaidVerifier extends AbstractVerifier {
47  
48      private final String externalJsScript;
49  
50      public MermaidVerifier(String externalJsScript) {
51          this.externalJsScript = externalJsScript;
52      }
53  
54      /**
55       * Verifies a HtmlPage.
56       *
57       * @param file the file to verify.
58       *
59       * @throws Exception if something goes wrong.
60       */
61      public void verify(String file) throws Exception {
62          File jsTest = getTestFile(file);
63          assertNotNull(jsTest);
64          assertTrue(jsTest.exists());
65  
66          // HtmlUnit
67          try (WebClient webClient = new WebClient(BrowserVersion.CHROME)) {
68              webClient.getOptions().setCssEnabled(false);
69              // the JS for Mermaid is too complex for HtmlUnit, so disable it and just verify the presence of the script
70              // element
71              webClient.getOptions().setJavaScriptEnabled(false);
72  
73              final List<String> collectedAlerts = new ArrayList<>(4);
74              webClient.setAlertHandler(new CollectingAlertHandler(collectedAlerts));
75  
76              HtmlPage page = (HtmlPage) webClient.getPage(jsTest.toURI().toURL());
77              assertNotNull(page);
78  
79              HtmlElement element = page.getHtmlElementById("contentBox");
80              assertNotNull(element);
81              HtmlMain main = (HtmlMain) element;
82              assertNotNull(main);
83  
84              Iterator<HtmlElement> elementIterator =
85                      main.getHtmlElementDescendants().iterator();
86  
87              // ----------------------------------------------------------------------
88              //
89              // ----------------------------------------------------------------------
90  
91              HtmlSection section = (HtmlSection) elementIterator.next();
92              assertNotNull(section);
93  
94              HtmlAnchor anchor = (HtmlAnchor) elementIterator.next();
95              assertNotNull(anchor);
96              assertEquals("Example_Mermaid_diagram", anchor.getAttribute("id"));
97              HtmlHeading1 h1 = (HtmlHeading1) elementIterator.next();
98              assertNotNull(h1);
99              assertEquals("Example Mermaid diagram", h1.asNormalizedText().trim());
100 
101             DomNodeList<DomElement> scripts = page.getElementsByTagName("script");
102             assertEquals(2, scripts.getLength());
103 
104             // first one is the external Mermaid script,
105             String scriptSrc = scripts.get(0).getAttribute("src");
106             assertTrue(scriptSrc.contains("mermaid"));
107 
108             if (externalJsScript != null) {
109                 assertEquals(externalJsScript, scripts.get(0).asXml());
110             } else {
111                 // check if file exists in site
112                 File scriptFile = new File(jsTest.getParentFile(), scriptSrc).getCanonicalFile();
113                 assertTrue(scriptFile.exists(), "Couldn't find referenced Mermaid file: " + scriptFile);
114             }
115 
116             // second one is the inline script to call the Mermaid API
117             scripts.get(1).asNormalizedText().trim().contains("mermaid.initialize");
118 
119             // code element should have been removed
120             DomNodeList<DomElement> codes = page.getElementsByTagName("code");
121             assertEquals(0, codes.getLength(), "code element should have been removed");
122 
123             // pre must carry the correct class attribute
124             DomNodeList<DomElement> pres = page.getElementsByTagName("pre");
125             assertEquals(1, pres.getLength(), "there should be exactly one pre element");
126             assertEquals("mermaid", pres.get(0).getAttribute("class"));
127         }
128     }
129 }