/* * 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 static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import com.google.common.base.Joiner; import com.google.common.css.SourceCode; import com.google.common.css.compiler.ast.BackDoorNodeMutation; import com.google.common.css.compiler.ast.CssBlockNode; import com.google.common.css.compiler.ast.CssDeclarationNode; import com.google.common.css.compiler.ast.CssNumericNode; import com.google.common.css.compiler.ast.CssPropertyNode; import com.google.common.css.compiler.ast.CssPropertyValueNode; import com.google.common.css.compiler.ast.CssRootNode; import com.google.common.css.compiler.ast.CssRulesetNode; import com.google.common.css.compiler.ast.CssSelectorNode; import com.google.common.css.compiler.ast.CssTree; import com.google.common.css.compiler.ast.GssParser; import com.google.common.css.compiler.ast.MutatingVisitController; import com.google.common.css.compiler.passes.testing.AstPrinter; import junit.framework.TestCase; /** * Unit tests for {@link MergeAdjacentRulesetNodesWithSameSelector}. * * @author oana@google.com (Oana Florescu) */ public class MergeAdjacentRulesetNodesWithSameSelectorTest extends TestCase { public void testRunPass() { MutatingVisitController visitController = createMock( MutatingVisitController.class); CssTree tree = createMock(CssTree.class); expect(tree.getMutatingVisitController()).andReturn(visitController) .anyTimes(); replay(tree); MergeAdjacentRulesetNodesWithSameSelector pass = new MergeAdjacentRulesetNodesWithSameSelector(tree); visitController.startVisit(pass); replay(visitController); pass.runPass(); verify(visitController); } public void testEnterTree() { CssTree tree = new CssTree((SourceCode) null); tree.getRulesetNodesToRemove().addRulesetNode(new CssRulesetNode()); assertFalse(tree.getRulesetNodesToRemove().getRulesetNodes().isEmpty()); MergeAdjacentRulesetNodesWithSameSelector pass = new MergeAdjacentRulesetNodesWithSameSelector(tree); pass.enterTree(tree.getRoot()); assertTrue(tree.getRulesetNodesToRemove().getRulesetNodes().isEmpty()); } public void testPassResult() throws Exception { CssTree tree = new GssParser(new SourceCode(null, lines( "@-moz-document url-prefix() {", " foo {", " padding: 6px;", " }", " foo {", " margin: 4px;", " }", "}", "foo, .bar #id {", " padding: 5px;", "}", "foo, .bar #id {", " margin: 2px;", "}"))).parse(); assertEquals( "[@-moz-document [url-prefix()]" + "{[foo]{[padding:[[6px]];]}[foo]{[margin:[[4px]];]}}" + "[foo,.bar #id]{[padding:[[5px]];]}" + "[foo,.bar #id]{[margin:[[2px]];]}]", AstPrinter.print(tree)); MergeAdjacentRulesetNodesWithSameSelector pass = new MergeAdjacentRulesetNodesWithSameSelector(tree); pass.runPass(); // As the elimination pass is not run here, we still have the one of the old // rulesets in each place. assertEquals( "[@-moz-document [url-prefix()]" + "{[foo]{[padding:[[6px]];margin:[[4px]];]}[foo]{[margin:[[4px]];]}}" + "[foo,.bar #id]{[padding:[[5px]];margin:[[2px]];]}" + "[foo,.bar #id]{[margin:[[2px]];]}]", AstPrinter.print(tree)); } public void testPassResult2() { CssPropertyNode prop1 = new CssPropertyNode("padding", null); CssPropertyValueNode value1 = new CssPropertyValueNode(); BackDoorNodeMutation.addChildToBack(value1, new CssNumericNode("5", "px")); CssDeclarationNode decl1 = new CssDeclarationNode(prop1); decl1.setPropertyValue(value1); CssPropertyNode prop2 = new CssPropertyNode("display", null); CssPropertyValueNode value2 = new CssPropertyValueNode(); BackDoorNodeMutation.addChildToBack(value2, new CssNumericNode("2", "px")); CssDeclarationNode decl2 = new CssDeclarationNode(prop2); decl2.setPropertyValue(value2); CssRulesetNode ruleset1 = new CssRulesetNode(); CssSelectorNode sel1 = new CssSelectorNode("foo", null); ruleset1.addSelector(sel1); ruleset1.addDeclaration(decl1); CssRulesetNode ruleset2 = new CssRulesetNode(); CssSelectorNode sel2 = new CssSelectorNode("foo", null); ruleset2.addSelector(sel2); ruleset2.addDeclaration(decl2); CssBlockNode body = new CssBlockNode(false); BackDoorNodeMutation.addChildToBack(body, ruleset1); BackDoorNodeMutation.addChildToBack(body, ruleset2); CssRootNode root = new CssRootNode(body); CssTree tree = new CssTree(null, root); assertEquals(tree.getRoot().getBody().toString(), "[[foo]{[padding:[5px]]}, [foo]{[display:[2px]]}]"); MergeAdjacentRulesetNodesWithSameSelector pass = new MergeAdjacentRulesetNodesWithSameSelector(tree, true); pass.runPass(); // skip merging rules with display -> we expect output == input assertEquals(tree.getRoot().getBody().toString(), "[[foo]{[padding:[5px]]}, [foo]{[display:[2px]]}]"); } private String lines(String... lines) { return Joiner.on("\n").join(lines); } }