/* * Copyright 2009 Google Inc. * * 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.google.common.css.compiler.passes; import com.google.common.base.Predicates; import com.google.common.collect.Iterables; import com.google.common.css.compiler.ast.CssFontFaceNode; import com.google.common.css.compiler.ast.CssImportBlockNode; import com.google.common.css.compiler.ast.CssImportRuleNode; import com.google.common.css.compiler.ast.CssMediaRuleNode; import com.google.common.css.compiler.ast.CssPageRuleNode; import com.google.common.css.compiler.ast.CssPageSelectorNode; import com.google.common.css.compiler.ast.CssTree; import com.google.common.css.compiler.ast.GssParserException; import com.google.common.css.compiler.passes.testing.PassesTestBase; /** * Unit tests for {@link CreateStandardAtRuleNodes}. * * @author fbenz@google.com (Florian Benz) */ public class CreateStandardAtRuleNodesTest extends PassesTestBase { @Override protected void runPass() { CreateStandardAtRuleNodes pass = new CreateStandardAtRuleNodes( tree.getMutatingVisitController(), errorManager); pass.runPass(); } public void testCharsetRemoval() throws Exception { parseAndRun("@charset \"x\";", "@charset removed"); assertTrue(isEmptyBody()); } public void testCreateSimpleImportNode() throws Exception { parseAndRun("@import \"name\" ;"); CssImportRuleNode importRule = findFirstNodeOf(CssImportRuleNode.class); assertEquals("import", importRule.getName().getValue()); assertEquals(1, importRule.getParametersCount()); assertTrue( "Import rules should occur in the import block.", Iterables.any( importRule.ancestors(), Predicates.instanceOf(CssImportBlockNode.class))); } public void testCreateUriImportNode() throws Exception { parseAndRun("@import url('/js/closure/css/common.css');"); CssImportRuleNode importRule = findFirstNodeOf(CssImportRuleNode.class); assertEquals("import", importRule.getName().getValue()); assertEquals(1, importRule.getParametersCount()); } public void testCreateComplexImportNode() throws Exception { parseAndRun("@import \"name\" param1, param2, param3;"); CssImportRuleNode importRule = findFirstNodeOf(CssImportRuleNode.class); assertEquals("import", importRule.getName().getValue()); assertEquals(2, importRule.getParametersCount()); } public void testImportWithoutParamError() throws Exception { parseAndRun("@import ;", "@import without a following string or uri"); assertTrue(isEmptyBody()); } public void testImportWithWrongParamError() throws Exception { parseAndRun("@import abc;", "@import's first parameter has to be a string or an url"); assertTrue(isEmptyBody()); } public void testImportWithTooManyParamsError() throws Exception { parseAndRun("@import \"A\" b c,d;" , "@import with too many parameters"); assertTrue(isEmptyBody()); } public void testMisplacedImportWarnings() throws Exception { CssTree t = parseAndRun("div { font-family: sans } @import 'a';", CreateStandardAtRuleNodes.IGNORE_IMPORT_WARNING_MESSAGE, CreateStandardAtRuleNodes.IGNORED_IMPORT_WARNING_MESSAGE); assertEquals( "This pass should not reorder misplaced nodes.", "(com.google.common.css.compiler.ast.CssRootNode " + "(com.google.common.css.compiler.ast.CssImportBlockNode)" + "(com.google.common.css.compiler.ast.CssBlockNode " + "(com.google.common.css.compiler.ast.CssRulesetNode " + "(com.google.common.css.compiler.ast.CssSelectorListNode " + "(com.google.common.css.compiler.ast.CssSelectorNode))" + "(com.google.common.css.compiler.ast.CssDeclarationBlockNode " + "(com.google.common.css.compiler.ast.CssDeclarationNode " + "(com.google.common.css.compiler.ast.CssPropertyValueNode " + "(com.google.common.css.compiler.ast.CssLiteralNode sans)))))" + "(com.google.common.css.compiler.ast.CssImportRuleNode)))", SExprPrinter.print(false /* includeHashCodes */, false /* withLocationAnnotation */, t)); } public void testPrintableImports() throws Exception { String css = "@import url('foo');div{font-family:sans}"; assertEquals( css, CompactPrinter.printCompactly(parseAndRun(css).getRoot())); } public void testCreateMediaNode1() throws Exception { parseAndRun("@media a, b, c { e.f { a:b } } "); assertTrue(getFirstActualNode() instanceof CssMediaRuleNode); CssMediaRuleNode mediaRule = (CssMediaRuleNode) getFirstActualNode(); assertEquals("media", mediaRule.getName().getValue()); assertEquals(1, mediaRule.getParametersCount()); } public void testCreateMediaNode2() throws Exception { parseAndRun("@media not screen { e.f { a:b } } "); assertTrue(getFirstActualNode() instanceof CssMediaRuleNode); } public void testCreateMediaNode3() throws Exception { parseAndRun("@media only screen { e.f { a:b } } "); assertTrue(getFirstActualNode() instanceof CssMediaRuleNode); } public void testCreateMediaNode4() throws Exception { parseAndRun("@media screen and (device-width:800px)," + "tv and (scan:progressive)," + "handheld and grid and (max-width:15em)" + "{ e.f { a:b } } "); assertTrue(getFirstActualNode() instanceof CssMediaRuleNode); } public void testCreateMediaNodeWithConditional() throws Exception { parseAndRun("@media screen {" + " @if (A) { e.f { a:b } }" + "@elseif (B) { e.f { a:b } }" + "@else { e.f { a:b } } }"); assertTrue(getFirstActualNode() instanceof CssMediaRuleNode); } public void testMediaWithoutBlockError() throws Exception { parseAndRun("@media a;", CreateStandardAtRuleNodes.NO_BLOCK_ERROR_MESSAGE); assertTrue(isEmptyBody()); } public void testMediaWithWrongBlockError() throws Exception { parseAndRun("@media a { @def a b; }", CreateStandardAtRuleNodes.MEDIA_INVALID_CHILD_ERROR_MESSAGE); assertTrue(isEmptyBody()); } public void testMediaWithoutParamError() throws Exception { parseAndRun("@media { }", CreateStandardAtRuleNodes.MEDIA_WITHOUT_PARAMETERS_ERROR_MESSAGE); assertTrue(isEmptyBody()); } public void testMediaInvalidParameterError1() throws Exception { parseAndRun("@media screen print {}", CreateStandardAtRuleNodes.INVALID_PARAMETERS_ERROR_MESSAGE); assertTrue(isEmptyBody()); } public void testMediaInvalidParameterError2() throws Exception { parseAndRun("@media screen a_d print {}", CreateStandardAtRuleNodes.INVALID_PARAMETERS_ERROR_MESSAGE); assertTrue(isEmptyBody()); } public void testMediaInvalidParameterError3() throws Exception { parseAndRun("@media screen, print a_d x {}", CreateStandardAtRuleNodes.INVALID_PARAMETERS_ERROR_MESSAGE); assertTrue(isEmptyBody()); } public void testMediaInvalidParameterError4() throws Exception { parseAndRun("@media not screen, print a_d x {}", CreateStandardAtRuleNodes.INVALID_PARAMETERS_ERROR_MESSAGE); assertTrue(isEmptyBody()); } public void testMediaInvalidParameterError5() throws Exception { parseAndRun("@media screen and (device-width:800px)," + "tv and (scan:progressive)," + "handheld and grid and (max-width:15em)," + "X Y" + "{ e.f { a:b } } ", CreateStandardAtRuleNodes.INVALID_PARAMETERS_ERROR_MESSAGE); assertTrue(isEmptyBody()); } public void testCreatePageNode() throws Exception { parseAndRun("@page { a:b }"); assertTrue(getFirstActualNode() instanceof CssPageRuleNode); CssPageRuleNode pageRule = (CssPageRuleNode) getFirstActualNode(); assertEquals("page", pageRule.getName().getValue()); assertEquals(0, pageRule.getParametersCount()); } public void testCreatePageWithPseudoClassNode1() throws Exception { parseAndRun("@page :left { a:b }"); assertTrue(getFirstActualNode() instanceof CssPageRuleNode); CssPageRuleNode pageRule = (CssPageRuleNode) getFirstActualNode(); assertEquals("page", pageRule.getName().getValue()); assertEquals(1, pageRule.getParametersCount()); assertEquals(":left", pageRule.getParameters().get(0).getValue()); } public void testCreatePageWithPseudoClassNode2() throws Exception { parseAndRun("@page artsy:right { a:b }"); assertTrue(getFirstActualNode() instanceof CssPageRuleNode); CssPageRuleNode pageRule = (CssPageRuleNode) getFirstActualNode(); assertEquals("page", pageRule.getName().getValue()); assertEquals(2, pageRule.getParametersCount()); assertEquals("artsy", pageRule.getParameters().get(0).getValue()); assertEquals(":right", pageRule.getParameters().get(1).getValue()); } public void testCreatePageWithTypeSelector() throws Exception { parseAndRun("@page artsy { a:b }"); assertTrue(getFirstActualNode() instanceof CssPageRuleNode); CssPageRuleNode pageRule = (CssPageRuleNode) getFirstActualNode(); assertEquals("page", pageRule.getName().getValue()); assertEquals(1, pageRule.getParametersCount()); assertEquals("artsy", pageRule.getParameters().get(0).getValue()); } public void testCreatePageInMedia() throws Exception { parseAndRun("@media print { @page { a:b } } "); assertTrue(getFirstActualNode() instanceof CssMediaRuleNode); CssMediaRuleNode mediaRule = (CssMediaRuleNode) getFirstActualNode(); assertEquals("media", mediaRule.getName().getValue()); assertEquals(1, mediaRule.getParametersCount()); assertEquals(1, mediaRule.getBlock().numChildren()); assertTrue(mediaRule.getBlock().getChildAt(0) instanceof CssPageRuleNode); CssPageRuleNode pageRule = (CssPageRuleNode) mediaRule.getBlock().getChildAt(0); assertEquals("page", pageRule.getName().getValue()); assertEquals(0, pageRule.getParametersCount()); } public void testCreatePageInMediaPseudoClass1() throws Exception { parseAndRun("@media print { @page XY:first { a:b } } "); assertTrue(getFirstActualNode() instanceof CssMediaRuleNode); CssMediaRuleNode mediaRule = (CssMediaRuleNode) getFirstActualNode(); assertEquals("media", mediaRule.getName().getValue()); assertEquals(1, mediaRule.getParametersCount()); assertEquals(1, mediaRule.getBlock().numChildren()); assertTrue(mediaRule.getBlock().getChildAt(0) instanceof CssPageRuleNode); CssPageRuleNode pageRule = (CssPageRuleNode) mediaRule.getBlock().getChildAt(0); assertEquals("page", pageRule.getName().getValue()); assertEquals(2, pageRule.getParametersCount()); assertEquals("XY", pageRule.getParameters().get(0).getValue()); assertEquals(":first", pageRule.getParameters().get(1).getValue()); } public void testCreatePageInMediaPseudoClass2() throws Exception { parseAndRun("@media print { @page :first { a:b } } "); assertTrue(getFirstActualNode() instanceof CssMediaRuleNode); CssMediaRuleNode mediaRule = (CssMediaRuleNode) getFirstActualNode(); assertEquals("media", mediaRule.getName().getValue()); assertEquals(1, mediaRule.getParametersCount()); assertEquals(1, mediaRule.getBlock().numChildren()); assertTrue(mediaRule.getBlock().getChildAt(0) instanceof CssPageRuleNode); CssPageRuleNode pageRule = (CssPageRuleNode) mediaRule.getBlock().getChildAt(0); assertEquals("page", pageRule.getName().getValue()); assertEquals(1, pageRule.getParametersCount()); assertEquals(":first", pageRule.getParameters().get(0).getValue()); } public void testPageRuleWithoutBlockError() throws Exception { parseAndRun("@page;", CreateStandardAtRuleNodes.NO_BLOCK_ERROR_MESSAGE); } public void testPageRuleInvalidParameters1() throws Exception { parseAndRun("@page one two three {}", CreateStandardAtRuleNodes.INVALID_PARAMETERS_ERROR_MESSAGE); } public void testPageRuleInvalidParameters2() throws Exception { parseAndRun("@page one two three {}", CreateStandardAtRuleNodes.INVALID_PARAMETERS_ERROR_MESSAGE); } public void testPageRuleInvalidParameters3() throws Exception { parseAndRun("@page one:invalidpseudopage {}", CreateStandardAtRuleNodes.INVALID_PARAMETERS_ERROR_MESSAGE); } public void testPageRuleInvalidParameters4() throws Exception { parseAndRun("@page :invalidpseudopage {}", CreateStandardAtRuleNodes.INVALID_PARAMETERS_ERROR_MESSAGE); } public void testCreatePageSelectorNode() throws Exception { createPageSelector("top-left"); createPageSelector("left-middle"); createPageSelector("bottom-right-corner"); createPageSelector("bottom-center"); } private void createPageSelector(String name) throws GssParserException { parseAndRun("@page { @" + name + " { a:b } }"); assertTrue(getFirstActualNode() instanceof CssPageRuleNode); CssPageRuleNode pageRule = (CssPageRuleNode) getFirstActualNode(); assertEquals("page", pageRule.getName().getValue()); assertEquals(1, pageRule.getBlock().numChildren()); assertTrue( pageRule.getBlock().getChildAt(0) instanceof CssPageSelectorNode); CssPageSelectorNode pageSelector = (CssPageSelectorNode) pageRule.getBlock().getChildAt(0); assertEquals(name, pageSelector.getName().getValue()); } public void testPageSelectorWithoutBlockError() throws Exception { parseAndRun("@page { @top-left; }", CreateStandardAtRuleNodes.NO_BLOCK_ERROR_MESSAGE); } public void testPageSelectorWithParametersError() throws Exception { parseAndRun("@page { @top-left param { } }", CreateStandardAtRuleNodes.PAGE_SELECTOR_PARAMETERS_ERROR_MESSAGE); } public void testCreateFontNode() throws GssParserException { parseAndRun("@font-face { font-family: Gentium }"); assertTrue(getFirstActualNode() instanceof CssFontFaceNode); CssFontFaceNode fontFace = (CssFontFaceNode) getFirstActualNode(); assertEquals("font-face", fontFace.getName().getValue()); assertEquals(0, fontFace.getParametersCount()); } public void testCreateFontNodeWithoutBlockError() throws GssParserException { parseAndRun("@font-face;", CreateStandardAtRuleNodes.NO_BLOCK_ERROR_MESSAGE); } public void testCreateFontNodeWithParametersError() throws Exception { parseAndRun("@font-face param { font-family: Gentium }", CreateStandardAtRuleNodes.FONT_FACE_PARAMETERS_ERROR_MESSAGE); } public void testMonochrome() throws Exception { parseAndRun( "@media (monochrome) {\n" + " .test { text-decoration: underline; }\n" + "}"); } public void testMediaAndAnd() throws Exception { parseAndRun( "@media (monochrome) and (min-width:800px) and (scan:progressive) {\n" + " .test { text-decoration: underline; }\n" + "}"); } public void testMinColorIndex() throws Exception { parseAndRun( "@media (min-color-index: 256) {\n" + " .test { font-color: red; }\n" + "}"); } }