/** * 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.supplementary.issues; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import javax.annotation.Nonnull; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.helger.css.ECSSVersion; import com.helger.css.decl.CSSStyleRule; import com.helger.css.decl.CascadingStyleSheet; import com.helger.css.reader.CSSReader; import com.helger.css.reader.CSSReaderSettings; import com.helger.css.reader.errorhandler.LoggingCSSParseErrorHandler; import com.helger.css.writer.CSSWriter; import com.helger.css.writer.CSSWriterSettings; /** * Test for issue 3: https://github.com/phax/ph-css/issues/3 * * @author Philip Helger */ public final class Issue3Test { private static final Logger s_aLogger = LoggerFactory.getLogger (Issue3Test.class); @Nonnull private static CascadingStyleSheet _parse (@Nonnull final String sCSS, final boolean bBrowserCompliantMode) { if (true) s_aLogger.info ("[Parsing] " + sCSS); return CSSReader.readFromStringReader (sCSS, new CSSReaderSettings ().setCSSVersion (ECSSVersion.CSS30) .setCustomErrorHandler (new LoggingCSSParseErrorHandler ()) .setBrowserCompliantMode (bBrowserCompliantMode)); } private static void _print (@Nonnull final CascadingStyleSheet aCSS) { s_aLogger.info (new CSSWriter (new CSSWriterSettings (ECSSVersion.CSS30).setOptimizedOutput (true)).setWriteHeaderText (false) .getCSSAsString (aCSS)); } @Test public void testErrorInStyleDeclarationBlock1 () { // Parse error in "unexpected:;" final String sTest = "body { background:red; unexpected:; background:blue; } span {color:blue;}"; // Expected output: // body { background:red; background:blue; } span {color:blue;} final CascadingStyleSheet aCSS = _parse (sTest, true); assertNotNull (aCSS); if (true) _print (aCSS); assertEquals (2, aCSS.getStyleRuleCount ()); // both backgrounds are present assertEquals (2, aCSS.getStyleRuleAtIndex (0).getDeclarationCount ()); } @Test public void testErrorInStyleDeclarationBlock1a () { // Parse error in "unexpected background" final String sTest = "body { background:red; unexpected background:blue; } span {color:blue;}"; // Expected output: // body { background:red; background:blue; } span {color:blue;} final CascadingStyleSheet aCSS = _parse (sTest, true); assertNotNull (aCSS); if (true) _print (aCSS); assertEquals (2, aCSS.getStyleRuleCount ()); // only first background is present assertEquals (1, aCSS.getStyleRuleAtIndex (0).getDeclarationCount ()); } @Test public void testErrorInStyleDeclarationBlock2 () { // Parse error at ".class" - nesting error which is afterwards closed final String sTest = "body {background:red;}" + "body {background:blue;.class{color:green}" + " body {background:green;}" + "}" + "body{background:orange;}"; final CascadingStyleSheet aCSS = _parse (sTest, true); assertNotNull (aCSS); if (true) _print (aCSS); assertEquals (3, aCSS.getStyleRuleCount ()); assertEquals (1, aCSS.getStyleRuleAtIndex (0).getDeclarationCount ()); assertEquals (1, aCSS.getStyleRuleAtIndex (1).getDeclarationCount ()); assertEquals (1, aCSS.getStyleRuleAtIndex (2).getDeclarationCount ()); } @Test public void testErrorInStyleDeclarationBlock2a () { // Parse error at ".class" - nesting error which is not closed afterwards final String sTest = "body1 {background:red;}\n" + "body2 {background:blue;.class{color:green}\n" + " body3 {background:green;}\n" + "body4{background:orange;}"; final CascadingStyleSheet aCSS = _parse (sTest, true); assertNotNull (aCSS); if (true) _print (aCSS); assertEquals (1, aCSS.getStyleRuleCount ()); assertEquals (1, aCSS.getStyleRuleAtIndex (0).getDeclarationCount ()); } @Test public void testErrorInMediaRule1 () { // Parse error in "unexpected:;" final String sTest = "@media print { div { color:red; unexpected:; align:top; } } span {color:blue;}"; final CascadingStyleSheet aCSS = _parse (sTest, true); assertNotNull (aCSS); if (false) _print (aCSS); assertEquals (1, aCSS.getMediaRuleCount ()); assertEquals (2, ((CSSStyleRule) aCSS.getMediaRuleAtIndex (0).getRuleAtIndex (0)).getDeclarationCount ()); assertEquals (1, aCSS.getStyleRuleCount ()); } @Test public void testErrorInKeyframeRule1 () { // Parse error in "unexpected::;" final String sTest = "@keyframes identifier { unexpected::; } span {color:blue;}"; final CascadingStyleSheet aCSS = _parse (sTest, true); assertNotNull (aCSS); if (false) _print (aCSS); assertEquals (1, aCSS.getKeyframesRuleCount ()); assertEquals (0, aCSS.getKeyframesRuleAtIndex (0).getBlockCount ()); assertEquals (1, aCSS.getStyleRuleCount ()); } @Test public void testErrorInKeyframeRule2 () { // Parse error in "unexpected::;" final String sTest = "@keyframes identifier { 0% { unexpected::; } 30% { top: 50px; } } span {color:blue;}"; final CascadingStyleSheet aCSS = _parse (sTest, true); assertNotNull (aCSS); if (true) _print (aCSS); assertEquals (1, aCSS.getKeyframesRuleCount ()); assertEquals (2, aCSS.getKeyframesRuleAtIndex (0).getBlockCount ()); assertEquals (1, aCSS.getStyleRuleCount ()); } @Test public void testErrorInKeyframeRule3 () { final String sTest = "body {background:red;}\n" + "@keyframes identifier { .class{color:red;.class{color:green} } \n" + "/* No matching closing bracket: the block is not closed and all the following rules are ignored. */\n" + "/* Add the \"}\" before the following rule to close the block and enable the rule */\n" + "body {background:green;}"; final CascadingStyleSheet aCSS = _parse (sTest, true); assertNotNull (aCSS); if (true) _print (aCSS); assertEquals (1, aCSS.getRuleCount ()); assertEquals (0, aCSS.getKeyframesRuleCount ()); } @Test public void testErrorInSupportsRule1 () { // Parse error in style declaration "unexpected::;" final String sTest = "@supports(column-count: 1) { body { unexpected::; } } span {color:blue;}"; final CascadingStyleSheet aCSS = _parse (sTest, true); assertNotNull (aCSS); if (true) _print (aCSS); assertEquals (1, aCSS.getSupportsRuleCount ()); assertEquals (1, aCSS.getSupportsRuleAtIndex (0).getRuleCount ()); assertEquals (0, ((CSSStyleRule) aCSS.getSupportsRuleAtIndex (0).getRuleAtIndex (0)).getDeclarationCount ()); assertEquals (1, aCSS.getStyleRuleCount ()); } }