/**
* Copyright 2015-2017 Linagora, Université Joseph Fourier, Floralis
*
* The present code is developed in the scope of the joint LINAGORA -
* Université Joseph Fourier - Floralis research program and is designated
* as a "Result" pursuant to the terms and conditions of the LINAGORA
* - Université Joseph Fourier - Floralis research program. Each copyright
* holder of Results enumerated here above fully & independently holds complete
* ownership of the complete Intellectual Property rights applicable to the whole
* of said Results, and may freely exploit it in any manner which does not infringe
* the moral rights of the other copyright holders.
*
* 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 net.roboconf.doc.generator;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Assert;
import org.junit.Test;
import org.xml.sax.InputSource;
import net.roboconf.core.internal.tests.TestUtils;
import net.roboconf.core.model.beans.Component;
import net.roboconf.core.model.beans.Instance;
import net.roboconf.core.model.helpers.ComponentHelpers;
import net.roboconf.core.utils.Utils;
import net.roboconf.doc.generator.RenderingManager.Renderer;
import nu.validator.messages.MessageEmitter;
import nu.validator.messages.MessageEmitterAdapter;
import nu.validator.messages.TextMessageEmitter;
import nu.validator.servlet.imagereview.ImageCollector;
import nu.validator.source.SourceCode;
import nu.validator.validation.SimpleDocumentValidator;
import nu.validator.xml.SystemErrErrorHandler;
/**
* @author Vincent Zurczak - Linagora
*/
public class RendererManagerHtmlTest extends AbstractTestForRendererManager {
@Test
public void checkHtmlValidatorWorks() throws Exception {
String content = "<html>hop</html>";
Assert.assertFalse( validateHtml( content ));
}
@Test
public void testSingleHtml_nullOptions() throws Exception {
Assert.assertEquals( 0, this.outputDir.listFiles().length );
this.rm.render( this.outputDir, this.alr.getApplicationTemplate(), this.applicationDirectory, Renderer.HTML, null, null );
verifySingleHtml( true );
}
@Test
public void testSingleHtml_emptyOptions() throws Exception {
Assert.assertEquals( 0, this.outputDir.listFiles().length );
Map<String,String> options = new HashMap<> ();
this.rm.render( this.outputDir, this.alr.getApplicationTemplate(), this.applicationDirectory, Renderer.HTML, options, null );
verifySingleHtml( true );
}
@Test
public void testSingleHtml_withoutInstances() throws Exception {
Assert.assertEquals( 0, this.outputDir.listFiles().length );
this.alr.getApplicationTemplate().getRootInstances().clear();
this.rm.render( this.outputDir, this.alr.getApplicationTemplate(), this.applicationDirectory, Renderer.HTML, null, null );
verifySingleHtml( true );
}
@Test
public void testSingleHtml_withReferencedCss() throws Exception {
Assert.assertEquals( 0, this.outputDir.listFiles().length );
Map<String,String> options = new HashMap<> ();
options.put( DocConstants.OPTION_HTML_CSS_REFERENCE, "http://hop.css" );
this.rm.render( this.outputDir, this.alr.getApplicationTemplate(), this.applicationDirectory, Renderer.HTML, options, null );
String content = verifySingleHtml( false );
Assert.assertFalse( content.contains( "style.css" ));
Assert.assertTrue( content.contains( "href=\"http://hop.css\"" ));
}
@Test
public void testSingleHtml_withCustomCss() throws Exception {
final String cssContent = "* { margin: 0; }";
File tempCssFile = this.folder.newFile();
Utils.writeStringInto( cssContent, tempCssFile );
Assert.assertEquals( 0, this.outputDir.listFiles().length );
Map<String,String> options = new HashMap<> ();
options.put( DocConstants.OPTION_HTML_CSS_FILE, tempCssFile.getAbsolutePath());
this.rm.render( this.outputDir, this.alr.getApplicationTemplate(), this.applicationDirectory, Renderer.HTML, options, null );
String content = verifySingleHtml( true );
Assert.assertTrue( content.contains( "href=\"style.css\"" ));
File cssFile = new File( this.outputDir, "style.css" );
Assert.assertTrue( cssFile.exists());
String readContent = Utils.readFileContent( cssFile );
Assert.assertEquals( cssContent, readContent );
}
@Test
public void testExplodedHtml_withReferencedCss() throws Exception {
Assert.assertEquals( 0, this.outputDir.listFiles().length );
Map<String,String> options = new HashMap<> ();
options.put( DocConstants.OPTION_HTML_CSS_REFERENCE, "http://hop.css" );
options.put( DocConstants.OPTION_HTML_EXPLODED, "boom" );
options.put( DocConstants.OPTION_HTML_HEADER_IMAGE_FILE, "inexisting-will-be-replaced-by-default" );
this.rm.render( this.outputDir, this.alr.getApplicationTemplate(), this.applicationDirectory, Renderer.HTML, options, null );
List<String> contents = verifyExplodedHtml( false );
for( int i=0; i<contents.size(); i++ ) {
String content = contents.get( i );
Assert.assertFalse( "Index " + i, content.contains( "style.css" ));
Assert.assertTrue( "Index " + i, content.contains( "href=\"http://hop.css\"" ));
}
}
@Test
public void testExplodedHtml_withCustomCssAndHeader() throws Exception {
final String cssContent = "* { padding: 0; }";
File tempCssFile = this.folder.newFile();
Utils.writeStringInto( cssContent, tempCssFile );
File roboconfImage = TestUtils.findTestFile( "/roboconf.jpg" );
File targetImage = this.folder.newFile();
Utils.copyStream( roboconfImage, targetImage );
Assert.assertTrue( targetImage.exists());
Assert.assertEquals( 0, this.outputDir.listFiles().length );
Map<String,String> options = new HashMap<> ();
options.put( DocConstants.OPTION_HTML_CSS_FILE, tempCssFile.getAbsolutePath());
options.put( DocConstants.OPTION_HTML_EXPLODED, "boom" );
options.put( DocConstants.OPTION_HTML_HEADER_IMAGE_FILE, targetImage.getAbsolutePath());
this.rm.render( this.outputDir, this.alr.getApplicationTemplate(), this.applicationDirectory, Renderer.HTML, options, null );
List<String> contents = verifyExplodedHtml( true );
int dotLevel = 0;
int twoDotsLevel = 0;
for( int i=0; i<contents.size(); i++ ) {
String content = contents.get( i );
if( content.contains( "href=\"style.css\"" ))
dotLevel ++;
else if( content.contains( "href=\"../style.css\"" ))
twoDotsLevel ++;
}
Assert.assertEquals( "Only index.html should contain href=\"style.css\"", 1, dotLevel );
Assert.assertEquals( "All the sections should contain href=\"../style.css\"", contents.size() - 1, twoDotsLevel );
File cssFile = new File( this.outputDir, "style.css" );
Assert.assertTrue( cssFile.exists());
String readContent = Utils.readFileContent( cssFile );
Assert.assertEquals( cssContent, readContent );
}
@Test
public void testExplodedHtml_customColorInOptions() throws Exception {
Assert.assertEquals( 0, this.outputDir.listFiles().length );
Map<String,String> options = new HashMap<> ();
options.put( DocConstants.OPTION_IMG_HIGHLIGHT_BG_COLOR, "#dddddd" );
options.put( DocConstants.OPTION_IMG_BACKGROUND_COLOR, "#4582ad" );
options.put( DocConstants.OPTION_IMG_FOREGROUND_COLOR, "#000000" );
options.put( DocConstants.OPTION_HTML_EXPLODED, "boom" );
this.rm.render( this.outputDir, this.alr.getApplicationTemplate(), this.applicationDirectory, Renderer.HTML, options, null );
verifyExplodedHtml( true );
}
/**
* Verifies assertions for the single HTML mode.
* @param hasStyleCss true if the output should contain a style.css file
* @return the file content (for additional checks)
*/
private String verifySingleHtml( boolean hasStyleCss ) throws Exception {
File f = new File( this.outputDir, "header.jpg" );
Assert.assertTrue( f.exists());
if( hasStyleCss ) {
f = new File( this.outputDir, "style.css" );
Assert.assertTrue( f.exists());
}
f = new File( this.outputDir, "png" );
Assert.assertTrue( f.isDirectory());
f = new File( this.outputDir, "index.html" );
Assert.assertTrue( f.exists());
int fileCount = hasStyleCss ? 4 : 3;
Assert.assertEquals( fileCount, this.outputDir.listFiles().length );
return verifyHtml( f );
}
/**
* Verifies assertions for the exploded HTML mode.
* @param hasStyleCss true if the output should contain a style.css file
* @return the generated files' content (for additional checks)
*/
private List<String> verifyExplodedHtml( boolean hasStyleCss ) throws Exception {
List<String> result = new ArrayList<> ();
File f = new File( this.outputDir, "header.jpg" );
Assert.assertTrue( f.exists());
if( hasStyleCss ) {
f = new File( this.outputDir, "style.css" );
Assert.assertTrue( f.exists());
}
f = new File( this.outputDir, "png" );
Assert.assertTrue( f.isDirectory());
f = new File( this.outputDir, "components" );
Assert.assertTrue( f.isDirectory());
f = new File( this.outputDir, "instances" );
Assert.assertTrue( f.isDirectory());
f = new File( this.outputDir, "index.html" );
Assert.assertTrue( f.exists());
int fileCount = hasStyleCss ? 6 : 5;
Assert.assertEquals( fileCount, this.outputDir.listFiles().length );
result.add( verifyHtml( f ));
for( Component c : ComponentHelpers.findAllComponents( this.alr.getApplicationTemplate())) {
f = new File( this.outputDir, DocConstants.SECTION_COMPONENTS + c.getName() + ".html" );
Assert.assertTrue( f.getAbsolutePath(), f.exists());
result.add( verifyHtml( f ));
}
for( Instance i : this.alr.getApplicationTemplate().getRootInstances()) {
f = new File( this.outputDir, DocConstants.SECTION_INSTANCES + i.getName() + ".html" );
Assert.assertTrue( f.getAbsolutePath(), f.exists());
result.add( verifyHtml( f ));
}
return result;
}
/**
* Verifies a HTML file.
* @param f
* @return the file content (for additional checks)
*/
private String verifyHtml( File f ) throws Exception {
String content = Utils.readFileContent( f );
verifyContent( content );
Assert.assertTrue( "Invalid HTML file: ", validateHtml( content ));
return content;
}
/**
* Verifies that a HTML content is valid.
* @param content the HTML content
* @return true if it is valid, false otherwise
* @throws Exception
*/
private boolean validateHtml( String content ) throws Exception {
InputStream in = new ByteArrayInputStream( content.getBytes( "UTF-8" ));
ByteArrayOutputStream out = new ByteArrayOutputStream();
SourceCode sourceCode = new SourceCode();
ImageCollector imageCollector = new ImageCollector(sourceCode);
boolean showSource = false;
MessageEmitter emitter = new TextMessageEmitter( out, false );
MessageEmitterAdapter errorHandler = new MessageEmitterAdapter( sourceCode, showSource, imageCollector, 0, false, emitter );
errorHandler.setErrorsOnly( true );
SimpleDocumentValidator validator = new SimpleDocumentValidator();
validator.setUpMainSchema( "http://s.validator.nu/html5-rdfalite.rnc", new SystemErrErrorHandler());
validator.setUpValidatorAndParsers( errorHandler, true, false );
validator.checkHtmlInputSource( new InputSource( in ));
return 0 == errorHandler.getErrors();
}
}