| /* |
| * Copyright 2008 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.gwt.resources.client; |
| |
| import com.google.gwt.core.client.GWT; |
| import com.google.gwt.junit.client.GWTTestCase; |
| import com.google.gwt.resources.client.CssResource.Import; |
| import com.google.gwt.resources.client.CssResource.ImportedWithPrefix; |
| import com.google.gwt.resources.client.CssResource.Shared; |
| |
| /** |
| * Contains various full-stack tests of the CssResource system. |
| */ |
| public class CSSResourceTest extends GWTTestCase { |
| interface ChildResources extends Resources { |
| ChildResources INSTANCE = GWT.create(ChildResources.class); |
| |
| @Override |
| @Source("16x16.png") |
| ImageResource spriteMethod(); |
| } |
| |
| interface ConcatenatedResources extends ClientBundle { |
| @Source(value = {"concatenatedA.css", "concatenatedB.css"}) |
| CssResource css(); |
| } |
| |
| interface CssWithDefines extends CssResource { |
| String colorString(); |
| |
| double lengthFloat(); |
| |
| int lengthInt(); |
| |
| String lengthString(); |
| |
| int overrideInt(); |
| |
| @ClassName("overrideInt") |
| String overrideIntClass(); |
| |
| double percentFloat(); |
| |
| int percentInt(); |
| |
| double rawDouble(); |
| |
| float rawFloat(); |
| |
| int rawInt(); |
| |
| String multiValueBorderDef(); |
| } |
| |
| /** |
| * Regenerate this interface by running InterfaceGenerator over test.css. |
| */ |
| interface FullTestCss extends CssResource { |
| String affectedBySprite(); |
| |
| String blahA(); |
| |
| String css3Color(); |
| |
| String externalA(); |
| |
| String externalB(); |
| |
| String externalC(); |
| |
| String extraSpriteClass(); |
| |
| @ClassName("FAIL") |
| String fAIL(); |
| |
| @ClassName("may-combine") |
| String mayCombine(); |
| |
| @ClassName("may-combine2") |
| String mayCombine2(); |
| |
| @ClassName("may-merge") |
| String mayMerge(); |
| |
| @ClassName("may-not-combine") |
| String mayNotCombine(); |
| |
| @ClassName("may-not-combine2") |
| String mayNotCombine2(); |
| |
| @ClassName("may-not-merge") |
| String mayNotMerge(); |
| |
| @ClassName("may-not-merge-or-combine-because-of-this") |
| String mayNotMergeOrCombineBecauseOfThis(); |
| |
| String multiClassA(); |
| |
| String multiClassB(); |
| |
| String nestedSprite(); |
| |
| String replacement(); |
| |
| @ClassName("replacement-not-java-ident") |
| String replacementNotJavaIdent(); |
| |
| String spriteClass(); |
| |
| @ClassName("this-does-not-matter") |
| String thisDoesNotMatter(); |
| } |
| |
| interface HasDescendants extends CssResource { |
| String foo(); |
| } |
| |
| interface MyCssResource extends CssResource, MyNonCssResource { |
| @Override |
| @ClassName("replacement-not-java-ident") |
| String nameOverride(); |
| } |
| |
| interface MyCssResourceA extends MyCssResource, SharedClasses { |
| String local(); |
| |
| // This shouldn't make a difference |
| @Override |
| String replacement(); |
| } |
| |
| @ImportedWithPrefix("gwt-MyCssResourceB") |
| interface MyCssResourceB extends MyCssResource, SharedClasses { |
| String local(); |
| |
| @Override |
| String sharedOverrideClass(); |
| } |
| |
| /* |
| * Check type inheritance. |
| */ |
| interface MyCssResourceWithSprite extends MyCssResource { |
| String externalA(); |
| |
| String extraSpriteClass(); |
| |
| String multiClassA(); |
| |
| String multiClassB(); |
| } |
| |
| interface MyNonCssResource { |
| String nameOverride(); |
| |
| String replacement(); |
| } |
| |
| /** |
| * CssResource used to test that the compiler will pick up the right resource (.css or .gss) |
| * according to the module configuration. |
| */ |
| interface ResourceFileChooser extends CssResource { |
| String myClass(); |
| } |
| |
| interface NestedResources extends ClientBundle { |
| @Source("32x32.png") |
| DataResource dataMethod(); |
| |
| @Source("16x16.png") |
| ImageResource spriteMethod(); |
| } |
| |
| interface Resources extends ClientBundle { |
| Resources INSTANCE = GWT.create(Resources.class); |
| |
| @Source("siblingTestA.css") |
| MyCssResourceA a(); |
| |
| @Source("siblingTestB.css") |
| MyCssResourceB b(); |
| |
| @Source("test.css") |
| FullTestCss css(); |
| |
| @Source("32x32.png") |
| CustomDataResource customDataMethod(); |
| |
| @Source("16x16.png") |
| CustomImageResource customSpriteMethod(); |
| |
| @Source("32x32.png") |
| DataResource dataMethod(); |
| |
| // Test default extensions |
| CssWithDefines deftest(); |
| |
| @Source("unrelatedDescendants.css") |
| @Import(value = {MyCssResourceA.class, MyCssResourceB.class}) |
| HasDescendants descendants(); |
| |
| // Make sure an empty, no-op CssResource works |
| CssResource empty(); |
| |
| // Test nested ClientBundles |
| NestedResources nested(); |
| |
| @Source("16x16.png") |
| ImageResource spriteMethod(); |
| |
| ResourceFileChooser resourceFileChooser(); |
| |
| @Source("resourceFileChooser.css") |
| ResourceFileChooser resourceFileChooserWithSourceTargetingOneCssFile(); |
| |
| @Source("resourceFileChooser.gss") |
| ResourceFileChooser resourceFileChooserWithSourceTargetingOneGssFile(); |
| |
| @Source({"resourceFileChooser.css", "resourceFileChooser2.css"}) |
| ResourceFileChooser resourceFileChooserWithSourceTargetingCssFiles(); |
| |
| @Source({"resourceFileChooser.gss", "resourceFileChooser2.gss"}) |
| ResourceFileChooser resourceFileChooserWithSourceTargetingGssFiles(); |
| |
| @Source({"resourceFileChooser.css", "resourceFileChooser2.css", "resourceFileChooser3.css"}) |
| ResourceFileChooser resourceFileChooserWithSourceTargetingCssFilesWithoutGssFile(); |
| } |
| |
| interface SharedBase extends CssResource { |
| String unsharedClass(); |
| } |
| |
| @ImportedWithPrefix("gwt-Shared") |
| @Shared |
| interface SharedClasses extends SharedBase { |
| String sharedClass(); |
| |
| String sharedOverrideClass(); |
| } |
| |
| interface SiblingResources extends ClientBundle { |
| @Source("siblingTestA.css") |
| MyCssResourceA a(); |
| |
| @Source("siblingTestB.css") |
| MyCssResourceB b(); |
| } |
| |
| public static String red() { |
| return "orange"; |
| } |
| |
| @Override |
| public String getModuleName() { |
| return "com.google.gwt.resources.ResourcesCssTest"; |
| } |
| |
| public void report(String s) { |
| // Can be filled in if debugging. |
| System.out.println(s); |
| } |
| |
| public void testChildResources() { |
| Resources parentResource = GWT.create(Resources.class); |
| ChildResources childResource = GWT.create(ChildResources.class); |
| |
| assertEquals(parentResource.dataMethod().getName(), |
| childResource.dataMethod().getName()); |
| } |
| |
| public void testConcatenatedResource() { |
| ConcatenatedResources r = GWT.create(ConcatenatedResources.class); |
| String text = r.css().getText(); |
| assertTrue(text.contains(".partA")); |
| assertTrue(text.contains(".partB")); |
| } |
| |
| public void testCss() { |
| FullTestCss css = Resources.INSTANCE.css(); |
| String text = css.getText(); |
| |
| report(text); |
| |
| // Check the sprite |
| assertTrue(text.contains("height:16px")); |
| assertTrue(text.contains("width:16px")); |
| |
| // Check the value() expansion |
| assertTrue(text.contains("offset-left:\"guard\" 16px !important;")); |
| assertTrue(text.contains("offset:16px 16px;")); |
| |
| // Make sure renaming works |
| assertFalse("replacement".equals(css.replacement())); |
| assertTrue(text.contains("." + css.replacement())); |
| assertTrue(text.contains("." + css.replacement() + ":after")); |
| assertTrue(text.contains("." + css.replacementNotJavaIdent())); |
| |
| // Make sure renaming for multi-class selectors (.foo.bar) works |
| assertFalse("multiClassA".equals(css.multiClassA())); |
| assertFalse("multiClassB".equals(css.multiClassB())); |
| assertTrue(text.contains("." + css.multiClassA() + "." + css.multiClassB())); |
| |
| // Check static if evaluation |
| assertTrue(text.contains("static:PASSED;")); |
| assertFalse(text.contains("FAIL")); |
| |
| // Check runtime if evaluation |
| assertTrue(text.contains("runtime:PASSED;")); |
| |
| // Check interestingly-named idents |
| assertTrue(text.contains("-some-wacky-extension")); |
| assertTrue(text.contains("another-extension:-bar")); |
| assertTrue(text.contains("-unescaped-hyphen:-is-better")); |
| assertTrue(text.contains("with_underscore:_is_better")); |
| assertTrue(text.contains("ns\\:tag")); |
| assertTrue(text.contains("ns\\:tag:pseudo")); |
| assertTrue(text.contains("ns\\:tag::double-pseudo")); |
| assertTrue(text.contains("ns\\:tag::-webkit-scrollbar")); |
| |
| // Check escaped string values |
| assertTrue(text.contains("\"Hello\\\\\\\" world\"")); |
| |
| // Check values |
| assertFalse(text.contains("0.0;")); |
| assertFalse(text.contains("0.0px;")); |
| assertFalse(text.contains("0px;")); |
| assertTrue(text.contains("background-color:#fff;")); |
| assertTrue(text.contains("content:\"bar\";")); |
| |
| // Check invalid CSS values |
| assertTrue(text.contains("top:expression(document.compatMode==\"CSS1Compat\" ? documentElement.scrollTop:document.body.scrollTop \\ 2);")); |
| |
| // Check data URL expansion |
| assertTrue(text.contains("backgroundTopLevel:url('" |
| + Resources.INSTANCE.dataMethod().getSafeUri().asString() + "')")); |
| assertTrue(text.contains("backgroundNested:url('" |
| + Resources.INSTANCE.nested().dataMethod().getSafeUri().asString() + "')")); |
| assertTrue(text.contains("backgroundCustom:url('" |
| + Resources.INSTANCE.customDataMethod().getSafeUri().asString() + "')")); |
| assertTrue(text.contains("backgroundImage:url('" |
| + Resources.INSTANCE.spriteMethod().getSafeUri().asString() + "')")); |
| assertTrue(text.contains("backgroundImageNested:url('" |
| + Resources.INSTANCE.nested().spriteMethod().getSafeUri().asString() + "')")); |
| assertTrue(text.contains("backgroundImageCustom:url('" |
| + Resources.INSTANCE.customSpriteMethod().getSafeUri().asString() + "')")); |
| |
| // Check @eval expansion |
| assertTrue(text.contains(red() + ";")); |
| |
| // Check @def substitution |
| assertTrue(text.contains("50px")); |
| // Check @def substitution into function arguments |
| // Note that GWT transforms rgb(R, G, B) into #rrggbb form. |
| assertTrue(text.contains("-moz-linear-gradient(left, #007f00, #00007f 50%);")); |
| assertTrue(text.contains("-webkit-linear-gradient(left, #007f00, #00007f 50%);")); |
| assertTrue(text.contains("linear-gradient(to right, #007f00, #00007f 50%);")); |
| |
| // Check merging semantics |
| assertTrue(text.indexOf("static:PASSED") < text.indexOf("runtime:PASSED")); |
| assertTrue(text.indexOf("before:merge") != -1); |
| assertTrue(text.indexOf("before:merge") < text.indexOf("after:merge")); |
| assertTrue(text.indexOf("." + css.mayCombine() + ",." + css.mayCombine2()) != -1); |
| assertTrue(text.indexOf("merge:merge") != -1); |
| assertTrue(text.indexOf("merge:merge") < text.indexOf("." |
| + css.mayNotCombine())); |
| assertTrue(text.indexOf("may-not-combine") < text.indexOf("prevent:true")); |
| assertTrue(text.indexOf("prevent:true") < text.indexOf("prevent-merge:true")); |
| assertTrue(text.indexOf("prevent:true") < text.indexOf("." |
| + css.mayNotCombine2())); |
| |
| // Check commonly-used CSS3 constructs |
| assertTrue(text.contains("background-color:rgba(0, 0, 0, 0.5);")); |
| |
| // Check external references |
| assertEquals("externalA", css.externalA()); |
| assertTrue(text.contains(".externalA ." + css.replacement())); |
| assertTrue(text.contains(".externalB")); |
| assertTrue(text.contains(".externalC")); |
| |
| // Test font-face contents |
| assertTrue(text.contains("url(Foo.otf) format(\"opentype\");")); |
| } |
| |
| public void testDefines() { |
| Resources r = GWT.create(Resources.class); |
| CssWithDefines defines = r.deftest(); |
| |
| assertEquals(1, defines.rawInt()); |
| assertEquals(1.5F, defines.rawFloat()); |
| assertEquals(1.5, defines.rawDouble()); |
| |
| assertEquals(50, defines.lengthInt()); |
| assertEquals(1.5, defines.lengthFloat()); |
| |
| assertEquals(50, defines.percentInt()); |
| assertEquals(50.5, defines.percentFloat()); |
| |
| assertEquals("100px", defines.lengthString()); |
| assertEquals("#f00", defines.colorString()); |
| |
| assertEquals(10, defines.overrideInt()); |
| assertNotNull(defines.overrideIntClass()); |
| assertFalse("10px".equals(defines.overrideIntClass())); |
| assertFalse("10".equals(defines.overrideIntClass())); |
| |
| assertTrue( |
| // css |
| "1px solid rgba(0, 0, 0, 0.2)".equals(defines.multiValueBorderDef()) || |
| // gss |
| "1px solid rgba(0,0,0,0.2)".equals(defines.multiValueBorderDef()) |
| ); |
| } |
| |
| public void testEnsureInjected() { |
| Resources r = GWT.create(Resources.class); |
| assertTrue(r.empty().ensureInjected()); |
| |
| r = GWT.create(Resources.class); |
| assertFalse(r.empty().ensureInjected()); |
| |
| r = GWT.create(ChildResources.class); |
| assertTrue(r.empty().ensureInjected()); |
| } |
| |
| public void testFileChoice() { |
| // resource without @Source annotation |
| ResourceFileChooser css = Resources.INSTANCE.resourceFileChooser(); |
| // should use the css file. |
| String expectedCss = "." + css.myClass() + "{width:5px;}"; |
| assertEquals(expectedCss, css.getText()); |
| |
| // resource with @Source annotation targeting one .css file |
| css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingOneCssFile(); |
| // should use the css file. |
| assertEquals(expectedCss, css.getText()); |
| |
| // resource with @Source annotation targeting one .gss file |
| css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingOneGssFile(); |
| // should use the css file instead of the gss file |
| assertEquals(expectedCss, css.getText()); |
| |
| // resource with @Source annotation targeting several .css files |
| css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingCssFiles(); |
| // should use the css files. |
| expectedCss = "." + css.myClass() + "{width:5px;padding:5px;}"; |
| assertEquals(expectedCss, css.getText()); |
| |
| // resource with @Source annotation targeting several .gss files |
| css = Resources.INSTANCE.resourceFileChooserWithSourceTargetingGssFiles(); |
| // should use the css files instead of the gss files |
| assertEquals(expectedCss, css.getText()); |
| } |
| |
| public void testMultipleBundles() { |
| Resources r1 = GWT.create(Resources.class); |
| SiblingResources r2 = GWT.create(SiblingResources.class); |
| |
| assertEquals(r1.a().replacement(), r2.a().replacement()); |
| assertEquals(r1.b().replacement(), r2.b().replacement()); |
| |
| assertEquals(r1.a().sharedClass(), r2.b().sharedClass()); |
| assertFalse(r1.a().sharedOverrideClass().equals( |
| r2.b().sharedOverrideClass())); |
| assertFalse(r1.a().unsharedClass().equals(r2.b().unsharedClass())); |
| |
| String text = r1.descendants().getText(); |
| report(text); |
| assertEquals("foo", r1.descendants().foo()); |
| assertTrue(text.contains("." + r1.a().local() + " ." + r1.b().local())); |
| assertTrue(text.contains("." + r1.descendants().foo())); |
| assertTrue(text.contains(".bar")); |
| } |
| |
| public void testSiblingCSS() { |
| SiblingResources r = GWT.create(SiblingResources.class); |
| |
| assertFalse(r.a().replacement().equals(r.b().replacement())); |
| assertFalse(r.a().local().equals(r.b().local())); |
| |
| String a = r.a().getText(); |
| String b = r.b().getText(); |
| |
| report(a); |
| report(b); |
| |
| assertTrue(a.contains(".other")); |
| assertTrue(b.contains(".other")); |
| assertTrue(a.contains(r.a().local())); |
| assertTrue(b.contains(r.b().local())); |
| assertFalse(a.contains(r.b().local())); |
| assertFalse(b.contains(r.a().local())); |
| } |
| } |