/*
* 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"
+ "}");
}
}