/** * Copyright (C) 2014-2017 Philip Helger (www.helger.com) * philip[at]helger[dot]com * * 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.helger.css.reader; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.File; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import com.helger.commons.collection.ext.CommonsArrayList; import com.helger.css.ECSSVersion; import com.helger.css.decl.CSSDeclaration; import com.helger.css.decl.CSSExpressionMemberFunction; import com.helger.css.decl.CSSExpressionMemberMath; import com.helger.css.decl.CSSExpressionMemberTermSimple; import com.helger.css.decl.CSSExpressionMemberTermURI; import com.helger.css.decl.CSSStyleRule; import com.helger.css.decl.CascadingStyleSheet; import com.helger.css.decl.ICSSExpressionMember; import com.helger.css.reader.errorhandler.LoggingCSSParseErrorHandler; import com.helger.css.writer.CSSWriter; import com.helger.css.writer.CSSWriterSettings; /** * Test reading CSS 3.0 stuff * * @author Philip Helger */ @RunWith (Parameterized.class) public final class CSSReader30FuncTest extends AbstractFuncTestCSSReader { @Parameters (name = "{index}: browserCompliant={0}") public static Iterable <Object []> data () { return new CommonsArrayList <> (new Object [] { true }, new Object [] { false }); } public CSSReader30FuncTest (final boolean bBrowserCompliant) { super (StandardCharsets.UTF_8, false, bBrowserCompliant); } @Test public void testReadAll30Good () { testReadGood ("src/test/resources/testfiles/css30/good"); } @Test public void testReadAll30BadButSucceeding () { testReadGood ("src/test/resources/testfiles/css30/bad_but_succeeding"); } @Test public void testReadAll30Bad () { testReadBad ("src/test/resources/testfiles/css30/bad"); } @Test public void testReadAll30GoodButFailing () { testReadBad ("src/test/resources/testfiles/css30/good_but_failing"); } @Test public void testReadAll30BadButRecoverable () { testReadBadButRecoverable ("src/test/resources/testfiles/css30/bad_but_recoverable"); } @Test public void testReadAll30BadButRecoverableAndBrowserCompliant () { testReadBadButRecoverableAndBrowserCompliant ("src/test/resources/testfiles/css30/bad_but_recoverable_and_browsercompliant"); } @Test public void testReadAll30BadButBrowserCompliant () { testReadBadButBrowserCompliant ("src/test/resources/testfiles/css30/bad_but_browsercompliant"); } @Test public void testReadSpecialGood () { final ECSSVersion eVersion = ECSSVersion.CSS30; final Charset aCharset = StandardCharsets.UTF_8; final File aFile = new File ("src/test/resources/testfiles/css30/good/artificial/hacks2.css"); final CascadingStyleSheet aCSS = CSSReader.readFromFile (aFile, aCharset, eVersion); assertNotNull (aCSS); final String sCSS = new CSSWriter (eVersion, false).getCSSAsString (aCSS); assertNotNull (sCSS); if (false) m_aLogger.info (sCSS); } @Test public void testReadExpressions () { final ECSSVersion eVersion = ECSSVersion.CSS30; final CSSWriterSettings aCSSWS = new CSSWriterSettings (eVersion, false); final Charset aCharset = StandardCharsets.UTF_8; final File aFile = new File ("src/test/resources/testfiles/css30/good/artificial/test-expression.css"); final CascadingStyleSheet aCSS = CSSReader.readFromFile (aFile, aCharset, eVersion); assertNotNull (aCSS); assertEquals (1, aCSS.getRuleCount ()); assertEquals (1, aCSS.getStyleRuleCount ()); final CSSStyleRule aSR = aCSS.getStyleRuleAtIndex (0); assertEquals ("div", aSR.getSelectorsAsCSSString (aCSSWS, 0)); assertEquals (23, aSR.getDeclarationCount ()); int i = 0; for (final CSSDeclaration aDecl : aSR.getAllDeclarations ()) { final String sExpectedName = Character.toString ((char) ('a' + i)); assertEquals (sExpectedName, aDecl.getProperty ()); ++i; } CSSDeclaration aDecl; ICSSExpressionMember aMember; // a: -5 aDecl = aSR.getDeclarationOfPropertyName ("a"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("-5", aMember.getAsCSSString (aCSSWS)); // b: +5 aDecl = aSR.getDeclarationOfPropertyName ("b"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("+5", aMember.getAsCSSString (aCSSWS)); // c: 5 aDecl = aSR.getDeclarationOfPropertyName ("c"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("5", aMember.getAsCSSString (aCSSWS)); // d: -5.12 aDecl = aSR.getDeclarationOfPropertyName ("d"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("-5.12", aMember.getAsCSSString (aCSSWS)); // e: +5.12 aDecl = aSR.getDeclarationOfPropertyName ("e"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("+5.12", aMember.getAsCSSString (aCSSWS)); // f: 5.12 aDecl = aSR.getDeclarationOfPropertyName ("f"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("5.12", aMember.getAsCSSString (aCSSWS)); // g: -5.12% aDecl = aSR.getDeclarationOfPropertyName ("g"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("-5.12%", aMember.getAsCSSString (aCSSWS)); // h: +5.12% aDecl = aSR.getDeclarationOfPropertyName ("h"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("+5.12%", aMember.getAsCSSString (aCSSWS)); // i: 5.12% aDecl = aSR.getDeclarationOfPropertyName ("i"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("5.12%", aMember.getAsCSSString (aCSSWS)); // j: -5px aDecl = aSR.getDeclarationOfPropertyName ("j"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("-5px", aMember.getAsCSSString (aCSSWS)); // k: +5px aDecl = aSR.getDeclarationOfPropertyName ("k"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("+5px", aMember.getAsCSSString (aCSSWS)); // l: 5px aDecl = aSR.getDeclarationOfPropertyName ("l"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("5px", aMember.getAsCSSString (aCSSWS)); // m: 'string1' aDecl = aSR.getDeclarationOfPropertyName ("m"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("'string1'", aMember.getAsCSSString (aCSSWS)); // n: "string2" aDecl = aSR.getDeclarationOfPropertyName ("n"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("\"string2\"", aMember.getAsCSSString (aCSSWS)); // o: abc aDecl = aSR.getDeclarationOfPropertyName ("o"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("abc", aMember.getAsCSSString (aCSSWS)); // p: from aDecl = aSR.getDeclarationOfPropertyName ("p"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("from", aMember.getAsCSSString (aCSSWS)); // q: to aDecl = aSR.getDeclarationOfPropertyName ("q"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("to", aMember.getAsCSSString (aCSSWS)); // r: url(a.gif) aDecl = aSR.getDeclarationOfPropertyName ("r"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermURI); assertEquals ("url(a.gif)", aMember.getAsCSSString (aCSSWS)); // s: #123 aDecl = aSR.getDeclarationOfPropertyName ("s"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("#123", aMember.getAsCSSString (aCSSWS)); // t: function(5,6,abc) aDecl = aSR.getDeclarationOfPropertyName ("t"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberFunction); assertEquals ("function", ((CSSExpressionMemberFunction) aMember).getFunctionName ()); // 3 parameters and 2 commas assertEquals (5, ((CSSExpressionMemberFunction) aMember).getExpression ().getMemberCount ()); assertEquals ("function(5,6,abc)", aMember.getAsCSSString (aCSSWS)); // u: calc(4 + 5) aDecl = aSR.getDeclarationOfPropertyName ("u"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberMath); // 2 values and 1 operator assertEquals (3, ((CSSExpressionMemberMath) aMember).getMemberCount ()); assertEquals ("calc(4 + 5)", aMember.getAsCSSString (aCSSWS)); // v: inherit aDecl = aSR.getDeclarationOfPropertyName ("v"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("inherit", aMember.getAsCSSString (aCSSWS)); // w: u+1234 aDecl = aSR.getDeclarationOfPropertyName ("w"); assertNotNull (aDecl); assertEquals (1, aDecl.getExpression ().getMemberCount ()); aMember = aDecl.getExpression ().getMemberAtIndex (0); assertTrue (aMember instanceof CSSExpressionMemberTermSimple); assertEquals ("u+1234", aMember.getAsCSSString (aCSSWS)); // Write result final String sCSS = new CSSWriter (aCSSWS).getCSSAsString (aCSS); assertNotNull (sCSS); if (false) m_aLogger.info (sCSS); } @Test public void testSpecialCasesAsString () { final boolean bBrowserCompliantMode = isBrowserCompliantMode (); final CSSReaderSettings aSettings = new CSSReaderSettings ().setCSSVersion (ECSSVersion.CSS30) .setCustomErrorHandler (new LoggingCSSParseErrorHandler ()) .setBrowserCompliantMode (bBrowserCompliantMode); // Parsing problem String sCSS = ".class{color:red;.class{color:green}.class{color:blue}"; CascadingStyleSheet aCSS; CascadingStyleSheet aCSS2; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); assertNotNull (aCSS); assertEquals (bBrowserCompliantMode ? "" : ".class{color:red}.class{color:blue}", new CSSWriter (ECSSVersion.CSS30, true).getCSSAsString (aCSS)); sCSS = " \n/* comment */\n \n.class{color:red;}"; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); assertNotNull (aCSS); assertEquals (".class{color:red}", new CSSWriter (ECSSVersion.CSS30, true).getCSSAsString (aCSS)); // With Umlauts sCSS = "div { colör: räd; }"; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); assertNotNull (aCSS); assertEquals ("div{colör:räd}", new CSSWriter (new CSSWriterSettings (ECSSVersion.CSS30).setOptimizedOutput (true)).getCSSAsString (aCSS)); aCSS2 = CSSReader.readFromStringReader (sCSS, aSettings); assertNotNull (aCSS2); assertEquals ("div{colör:räd}", new CSSWriter (ECSSVersion.CSS30, true).getCSSAsString (aCSS2)); assertEquals (aCSS, aCSS2); // With masking sCSS = "#mask\\26{ color: red; }"; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); assertNotNull (aCSS); assertEquals ("#mask\\26{color:red}", new CSSWriter (new CSSWriterSettings (ECSSVersion.CSS30).setOptimizedOutput (true)).getCSSAsString (aCSS)); sCSS = "#mask\\26 { color: red; }"; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); assertNotNull (aCSS); assertEquals ("#mask\\26 {color:red}", new CSSWriter (new CSSWriterSettings (ECSSVersion.CSS30).setOptimizedOutput (true)).getCSSAsString (aCSS)); sCSS = "#mask\\26 { color: red; }"; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); assertNotNull (aCSS); assertEquals ("#mask\\26 {color:red}", new CSSWriter (new CSSWriterSettings (ECSSVersion.CSS30).setOptimizedOutput (true)).getCSSAsString (aCSS)); // With masking sCSS = "#mask\\x{ color: red; }"; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); assertNotNull (aCSS); assertEquals ("#mask\\x{color:red}", new CSSWriter (new CSSWriterSettings (ECSSVersion.CSS30).setOptimizedOutput (true)).getCSSAsString (aCSS)); sCSS = "#mask\\x { color: red; }"; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); assertNotNull (aCSS); assertEquals ("#mask\\x{color:red}", new CSSWriter (new CSSWriterSettings (ECSSVersion.CSS30).setOptimizedOutput (true)).getCSSAsString (aCSS)); sCSS = "#mask\\x { color: red; }"; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); assertNotNull (aCSS); assertEquals ("#mask\\x{color:red}", new CSSWriter (new CSSWriterSettings (ECSSVersion.CSS30).setOptimizedOutput (true)).getCSSAsString (aCSS)); // With charset rule defined sCSS = "@charset \"iso-8859-1\"; div{color:red ; }"; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); assertNotNull (aCSS); assertEquals ("div{color:red}", new CSSWriter (new CSSWriterSettings (ECSSVersion.CSS30).setOptimizedOutput (true)).getCSSAsString (aCSS)); // Invalid identifier 1 sCSS = "-0{color:red;}"; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); assertNull (aCSS); // Invalid identifier 2 sCSS = "$0{color:red;}"; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); assertNull (aCSS); // Invalid identifier 3 sCSS = "*0{color:red;}"; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); if (bBrowserCompliantMode) { assertNotNull (aCSS); assertEquals (1, aCSS.getRuleCount ()); } else assertNull (aCSS); // Valid version of previous variant sCSS = "*abc{color:red;}"; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); assertNotNull (aCSS); assertEquals ("*abc{color:red}", new CSSWriter (new CSSWriterSettings (ECSSVersion.CSS30).setOptimizedOutput (true)).getCSSAsString (aCSS)); // Invalid identifier 4 sCSS = "0{color:red;}"; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); assertNull (aCSS); // Invalid identifier 5 sCSS = "--{color:red;}"; aCSS = CSSReader.readFromStringReader (sCSS, aSettings); assertNull (aCSS); } }